Slide 1

Slide 1 text

Deploy & Manage Kubernetes on SakuraCloud 2019/11/05 さくらの夕べ Docker/Kubernetesナイト #2

Slide 2

Slide 2 text

whoami ● 金澤 直輝 ● 技術本部 ミドルウェアグループ ● ストレージチーム ○ コンパネ・API 側 ● 新卒2年目 ● twitter: @hnron 2

Slide 3

Slide 3 text

今日話すこと ● さくら内での事例紹介 ○ 新サービスのインフラに Kubernetesを導入した話 ● さくらのクラウドにkubernetesをデプロイする ○ ざっくりした流れと、コツなど ● この2つの話をしながらさくらのクラウドに kubernetesを乗せる時のコツ?を紹介します (さくらのクラウド側の tipsがメインになりそう) 3

Slide 4

Slide 4 text

対象 ● Kubernetesは触ったことがある ● さくらのクラウド上でk8sをやっていきたい方 4

Slide 5

Slide 5 text

「新サービスのインフラに Kubernetesを導入した話」 5

Slide 6

Slide 6 text

どこに導入したの? (ΦωΦ) ● とある新規サービスの 「Cpanel and API Team」チーム ○ コンパネ・APIのインフラにKubernetesを導入した ● メンバー ○ API開発 ■ @chibiegg ■ @amaya382 ■ @asya_aoi1049 ■ もう一人 ○ 監視 / Manifest管理 ■ @kameneko1004 ○ Kubernetes管理 ■ わたし 6

Slide 7

Slide 7 text

どこに導入したの? (ΦωΦ) ストレージ バックエンド さくらのクラウド Kubernetes API コンパネ 7 こ っ ち internet

Slide 8

Slide 8 text

アーキテクチャ 8

Slide 9

Slide 9 text

アーキテクチャ > v2 9 物理側 バックボーン さくらのクラウド VPN VPN Authn Proxy Secure Proxy RProxy ⇆ worker etcd master worker RProxy ⇆ internet hybrid 接続 ストレージ バックエンド etcd x5 master x3 worker xN台~ プロクシ側で完結する アプリケーションだけ こっちに置くなど internet

Slide 10

Slide 10 text

アーキテクチャ > v3 10 物理側 バックボーン さくらのクラウド VPN VPN Authn Proxy Secure Proxy RProxy ⇆ worker etcd master worker RProxy ⇆ internet hybrid 接続 ストレージ バックエンド internet 物理にまたがった構 成をやめた 4core/8G or 4core/16G くらいのスペックを 横に並べている 物理とまたがった構成を解除 ライフサイクルが異なる - RProxyは1度建てたらほぼその まま運用できる - k8sは数ヶ月ごとに Upgrade etcd x5 master x3 worker x7~

Slide 11

Slide 11 text

CNI 11

Slide 12

Slide 12 text

CNI ● Calicoを採用 ○ L3ピュアでの通信 (BGP) ○ NetworkPolicyが使える ○ 物理側NWとは CrossSubnet Modeの IPIPトンネルでカプセリング ● CrossSubnet ○ 同セグメント内のPod通信は直接ルーティングし、別セグメントなら IPIPでカプセリング ○ セグメント間のルータが BGPを喋れるなら必要ない ○ よしなにカプセリングしたりさせなかったり 12

Slide 13

Slide 13 text

Calico - Cross Subnet 13 物理側 さくらのクラウド RProxy ⇆ worker etcd master worker RProxy ⇆ internet hybrid 接続 ストレージ バックエンド このNWをまたがった部分の Pod間通信の話

Slide 14

Slide 14 text

Calico - Cross Subnet 14 物理 さくらのクラウド ⇆ worker 3 worker 1 worker 2 ⇆ hybrid 接続 worker 5 worker 4 Host subnet 192.168.0.0/24 Host subnet 192.168.99.0/24 .21 .22 .23 .200 .31 .32 .200 10.0.65.0/26 10.0.66.0/26 10.0.67.0/26 10.0.70.0/26 10.0.71.0/26 Cluster Subnet (pod CIDR)

Slide 15

Slide 15 text

Calico - Cross Subnet 15 物理 さくらのクラウド ⇆ worker 3 worker 1 worker 2 ⇆ hybrid 接続 worker 5 worker 4 192.168.0.0/24 192.168.99.0/24 .21 .22 .23 .200 .31 .32 .200 10.0.65.0/26 10.0.66.0/26 10.0.67.0/26 10.0.70.0/26 10.0.71.0/26 Cluster Subnet (pod CIDR) Nodeが同じSubnet内に いる場合は、その上の Pod間通信はBGPで直接 ルーティングされる こっちも同じ

Slide 16

Slide 16 text

Calico - Cross Subnet 16 物理 さくらのクラウド ⇆ worker 3 worker 1 worker 2 ⇆ hybrid 接続 worker 5 worker 4 192.168.0.0/24 192.168.99.0/24 .21 .22 .23 .200 .31 .32 .200 10.0.65.0/26 10.0.66.0/26 10.0.67.0/26 10.0.70.0/26 10.0.71.0/26 Nodeが異なるSubnetに いる場合は、その上の Pod間通信はIPIPでカプ セリングされる Cluster Subnet (pod CIDR) ここらへんにいるルータに各ホ ストとPodNetworkのルーティン グを追加しなくて済む (BGPを喋れない場合も)

Slide 17

Slide 17 text

ユーザ管理 17

Slide 18

Slide 18 text

ユーザ管理 (kubectl を叩く人) ● クライアント証明書認証 ○ kubespray(kubeadm)などで構築するとデフォルトで用意される kubeconfig はこれ ○ CRL(証明書失効リスト)をkube-apiserverに持たせることが現状不可 ■ https://github.com/kubernetes/kubernetes/issues/18982 ● ServiceAccount ○ 一応 ServiceAccount はあくまでアプリケーション用 ○ ユーザ単位で作成・削除は出来る ○ 人が増えまくると管理が大変になるらしい ● oidc (OpenID Connect) 認証 ○ keycloakなどでかぶせればAD認証が可能になる ○ kubeloginなどのツールと合わせて使う 18

Slide 19

Slide 19 text

「さくらのクラウドに KubernetesをデプロイするときのTips」 19

Slide 20

Slide 20 text

ざっくりと流れ 20 ● デプロイ ○ サーバの展開 (Terraform) ○ Dynamic Inventoryを実装 ○ サーバの初期設定 (Ansible) ○ Kubernetes cluster をデプロイ (kubespray) ● おまけ ○ Cluster Upgrade

Slide 21

Slide 21 text

前提 21 ● さくらのクラウドのアカウントを持っていること ● APIのAccess KeyとSecretを発行済なこと

Slide 22

Slide 22 text

今回のお話で出てくる構成(雑) 22

Slide 23

Slide 23 text

今回のお話で出てくる構成(雑) 23 さくらのクラウド master node x n台 - kubelet - kube-apiserver - kube-scheduler - kube-controller-manager worker node x n台 - kube-apiserver - kube-scheduler - kube-controller-manager etcd node x n台 - etcd スイッチ

Slide 24

Slide 24 text

デプロイ 24

Slide 25

Slide 25 text

デプロイ > サーバの展開 25 ● terraformで行う ○ https://github.com/naoki912/example-sacloud-kubernetes/tree/master/terraform ● ゴール ○ Switchを作成できる ○ サーバを作成できる ○ 後述するDynamic Inventoryで使うタグを設定する ● やること ○ terraformを書く!

Slide 26

Slide 26 text

デプロイ > サーバの初期設定 ● Ansibleで行う ○ https://github.com/naoki912/example-sacloud-kubernetes/tree/master/ansible ● ゴール ○ kubesprayを流し込める状態にする ● やること ○ nfs-common をインストール ■ PVにNFSアプライアンスを使う場合 ○ IPv4 Forwarding の設定 ○ DSRの設定 ■ type LoadBalancer (sakura-cloud-controller-manager) を使う場合 ○ swapの無効化 26

Slide 27

Slide 27 text

デプロイ > サーバの初期設定 > swap無効化のコツ ● systemd が動いているOSでのswap無効化のコツ ○ systemdが勝手にswapパーティションを見つけてきて有効にしてしまう ● 通常なら ○ swapoff ○ fstabからswapを削除 ● systemd ○ *.swap をmask ● Ubuntuアーカイブなら dev-vda2.swap を決め打ちでmaskしてok ○ 多分これが一番早いと思います 27 - name: mask swap systemd: name: dev-vda2.swap masked: yes $ sudo systemctl mask dev-vda2.swap

Slide 28

Slide 28 text

デプロイ > サーバの初期設定 > DSR ● type LoadBalancer を使う場合は設定する ○ sakura-cloud-controller-manager はLBアプライアンスを使用している ○ https://github.com/sacloud/sakura-cloud-controller-manager ● https://manual.sakura.ad.jp/cloud/network/load-balancer.html#id15 ● https://github.com/naoki912/example-sacloud-kubernetes/blob/079b15baa11e51e808a1be0a5da4cd9bacc22417/ans ible/roles/kubespray_pre/tasks/main.yml#L19-L34 28

Slide 29

Slide 29 text

デプロイ > kubespray 29 ● https://github.com/kubernetes-sigs/kubespray ○ Ansible + kubeadm ○ etcd含めHAクラスタをサポート ○ dockerのインストールから面倒を見てくれる ○ kube-apiserverの前段のLBを用意しなくて済む ■ kube-apiserverへリバプロするNginxのStaticPodがnode上に展開される worker master kubelet Nginx StaticPod kube-apiserver upstream kube_apiserver { server 192.168.0.9:6443; server 192.168.0.10:6443; } server { listen 127.0.0.1:6443; proxy_pass kube_apiserver; } # /etc/kubernetes/kubelet.conf apiVersion: v1 clusters: - cluster: certificate-authority-data: XXXX server: https://localhost:6443 name: default-cluster master kube-apiserver

Slide 30

Slide 30 text

デプロイ > kubespray > つらいとこ ● playbookの実行に時間がかかる (1時間くらい) ○ スケールアウトに時間がかかる ● アップグレード時はけっこうバグを踏むのでちゃんと検証しよう ● 設定変更やスケール時はクラスタを破壊しないように注意 ○ ミスって別バージョンの etcdのkubesprayを流すとクラスタが破壊される可能性 ○ etcdのマイナーバージョンが変わるタイミングでダウングレードしちゃって止まるとか 30

Slide 31

Slide 31 text

デプロイ > kubespray > 対象 31 31 さくらのクラウド ⇆ worker etcd master internet type LB

Slide 32

Slide 32 text

デプロイ > kubespray > 対象 32 32 さくらのクラウド ⇆ worker etcd master internet type LB worker etcd master

Slide 33

Slide 33 text

デプロイ > kubespray > 対象 33 vm ⇆ vm vm kubespray 実行マシン vm vm vm

Slide 34

Slide 34 text

デプロイ > kubespray > 対象 34 ⇆ etcd - docker - etcd etcd - docker - etcd kubespray 実行マシン master - docker - kubelet - kube-apiserver - kube-scheduler - kube-controller-manager master - docker - kubelet - kube-apiserver - kube-scheduler - kube-controller-manager worker - docker - kubelet - nginx (StaticPod) worker - docker - kubelet - nginx (StaticPod)

Slide 35

Slide 35 text

デプロイ > kubespray > kubesprayの設定 ● 実行環境 ● project tree ● option 35

Slide 36

Slide 36 text

デプロイ > kubespray > kubesprayの設定 > 実行環境 ● pyenv を利用する (環境を切り替えられれば他のものでok) ● pythonのバージョンは何でも良い ● ansibleのバージョンは requirements.txt で必ず合わせる ○ 最新バージョンのansibleで実行するとコケる (kubespray v2.8) 36 $ pyenv virtualenv 3.7.2 kubespray-v2.10.4 $ pyenv activate kubespray-v2.10.4 $ pyenv exec pip install -r requirements.txt

Slide 37

Slide 37 text

デプロイ > kubespray > kubesprayの設定 > project tree ● kubespray の group_vars に直接書き込まない! ● group_varsはsampleのsymlinkを張る (中身は触らない) ● 設定変更はextra_varsで渡す ○ 変更する変数だけ定義する ○ 設定はgit管理 ● 何を変更したか分かるように 37 . (project root) ├── credentials/ │ ├── dev.kubeadm_certificate_key.creds │ ├── dev.kube_encrypt_token.creds │ ├── lab.kube_encrypt_token.creds │ ├── prd.kube_encrypt_token.creds │ └── stg.kube_encrypt_token.creds ├── extra_vars_all.yml ├── inventory/ │ ├── credentials -> ../credentials │ ├── group_vars -> ../kubespray/inventory/sample/group_vars │ ├── inventory.py* │ ├── dev.ini │ └── prd.ini ├── kubespray/ -> git submodule ├── .python-version └── README.md extra_varsに設定されている変数は group_varsを上書きしてくれる 設定項目が多いので group_varsを直接編集すると何を変更したか 分からなくなる Dynamic Inventory については後述

Slide 38

Slide 38 text

デプロイ > kubespray > kubesprayの設定 > option ● ほぼほぼデフォルトのままで問題ない 38 # https://github.com/naoki912/example-sacloud-kubernetes/blob/master/kubespray/extra_vars_all.yml etcd_memory_limit: "2048M" # WARNING: BUG # https://github.com/kubernetes-sigs/kubespray/issues/4917 # https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/configuration.md#--quota-backend-bytes etcd_quota_backend_bytes: "0" # クラスタの使用目的によっては無効化 podsecuritypolicy_enabled: false # dashboardを無効化 dashboard_enabled: false # group_vars/k8s-cluster/addons.yml # 使いたいものがある場合 helm_enabled: false registry_enabled: false ...

Slide 39

Slide 39 text

デプロイ > kubespray > kubesprayの設定 > option ● etcdの暗号化をする場合は必要に応じてsecretを置くディレクトリも調整 39 ## Encrypting Secret Data at Rest (experimental) kube_encrypt_secret_data: true # example: inventory/credentials/dev.kube_encrypt_token.creds kube_encrypt_token: "{{ lookup('password', credentials_dir + '/' + env + '.kube_encrypt_token.creds length=32 chars=ascii_letters,digits') }}"

Slide 40

Slide 40 text

デプロイ > kubespray > upgrade 40 ● リリースノートとgroup_varsのdiffを見ておく ○ デフォルトのパラメータが変わることがある ● 必ず検証 ○ 検証環境に本番と同じようにアプリケーションをデプロイした状態で行う

Slide 41

Slide 41 text

デプロイ > kubespray > kubesprayバグ集 ● v2.8.3(v1.12.5) -> v2.9.0(v1.13.5) ○ 「calicoが壊れてworkerが全てNotReadyになる」 ○ nodelocaldns がデフォルトで有効になったタイミングだったはず ● v2.10.4(v1.14.3) -> v2.11.0(v1.15.3) ○ 「デフォルト定義の etcd_quota_backend_bytes: "2G" でetcdの起動に失敗する」 ○ ロールバックしようとして前のバージョンの playbookを流すとetcdがクラッシュ ■ etcdのマイナーバージョンが切り替わったタイミングだった 41

Slide 42

Slide 42 text

事前準備 Ansible Dynamic Inventory 42

Slide 43

Slide 43 text

事前準備 > Dynamic Inventory ● モチベーション ○ スケール時に可能な限り inventoryファイルを操作したくない ○ inventoryの編集忘れを防ぎたい 43

Slide 44

Slide 44 text

事前準備 > Dynamic Inventory > group by どれ...? ● さくらのクラウドのサーバにはタグを付けることが出来る ○ そのタグ(server_tags)をベースにgroupを生成 ● タグはterraformなどで構築する時に設定すればok 44 ↓これ

Slide 45

Slide 45 text

@with_sacloud_inventory @with_kubespray_inventory @cluster=example @instance-type=large k8s-cluster kube-master @sshconfig @ssh_user=ubuntu @ssh_bastion_group=group1 server_tags 事前準備 > Dynamic Inventory > group ● server_tagsから生成する 45 # 手で書くなら [kube-master] node1 node2 [etcd] node1 node2 node3 [kube-node] node2 node3 node4 node5 node6 # Dynamic Inventory # 実際にはjsonを吐く [@cluster=example] node1 node2 ... [kube-master] node1 [kube-node] node2 [@instance-type=large] node2 ... [@sshconfig] [@ssh_user=ubuntu] [@with_kubespray_inventory] [@with_sacloud_inventory] この server_tags から生成する # Dynamic Inventory { "@cluster=example": { "hosts": [ "server-01", "server-02", "server-03" ] }, "kube-master": { "hosts": [ "server-01", "server-02" ] }, "etcd": { "hosts": [ "server-01" ] }, "kube-node": { "hosts": [ "server-02", "server-03" ] } }

Slide 46

Slide 46 text

@with_sacloud_inventory @with_kubespray_inventory @cluster=example @instance-type=large k8s-cluster kube-master @sshconfig @ssh_user=ubuntu @ssh_bastion_group=group1 server_tags 事前準備 > Dynamic Inventory > group ● groupは3種類の使い方をする ○ filter ■ 複数クラスタを巻き込まないように対象のクラスタのみに filter ○ kubesprayが使用するgroup ■ kube-master, kube-node, etcd, k8s-cluster(kube-master, kube-node) ○ nodeごとに設定したい変数などがある場合に使う group ■ @instance-type= 46

Slide 47

Slide 47 text

@with_sacloud_inventory @with_kubespray_inventory @cluster=example @instance-type=large k8s-cluster kube-master @sshconfig @ssh_user=ubuntu @ssh_bastion_group=group1 server_tags 事前準備 > Dynamic Inventory > group > filter ● 同じzoneに複数k8sが存在する場合は必須 ● どのクラスタに対してkubesprayを実行するか判断 47 クラスタA クラスタB node node node node node node node node tag @cluster=a tag @cluster=b 「@cluster=b」 のみplaybookを実行 (タグに「@cluster=b」が 設定されていないサーバ をinventoryに含めない)

Slide 48

Slide 48 text

@with_sacloud_inventory @with_kubespray_inventory @cluster=example @instance-type=large k8s-cluster kube-master @sshconfig @ssh_user=ubuntu @ssh_bastion_group=group1 server_tags 事前準備 > Dynamic Inventory > group > kubespray用 ● kubesprayが利用するgroup ○ ↓の4種類のgroupを見てnodeをデプロイする ○ kube-master, kube-node, etcd, (k8s-cluster) ○ 同じサーバに「etcd, kube-master」などのgroupを割り当てれば同居可能 48

Slide 49

Slide 49 text

@with_sacloud_inventory @with_kubespray_inventory @cluster=example @instance-type=large k8s-cluster kube-master @sshconfig @ssh_user=ubuntu @ssh_bastion_group=group1 server_tags 事前準備 > Dynamic Inventory > group > 特殊な設定用 ● 一部のnodeのみ特殊な設定を入れたい時に利用する ● inventoryのgroupにkubesprayで使う変数を設定する ○ 「@instance-type=」groupに「node_labels」変数を設定するなど 49 # inventory/dev-hosts.ini [@instance-type=large:vars] node_labels={"beta.kubernetes.io/instance-type":"large"} # groupに対してvarsを設定する [test_group:vars] key=value

Slide 50

Slide 50 text

@with_sacloud_inventory @with_kubespray_inventory @cluster=example @instance-type=large k8s-cluster kube-master @sshconfig @ssh_user=ubuntu @ssh_bastion_group=group1 server_tags 事前準備 > Dynamic Inventory > 実装 50 ● https://github.com/naoki912/example-sacloud-kubernetes/blob/master/kubesp ray/inventory/kube_sacloud_inventory.py ● https://github.com/naoki912/example-sacloud-kubernetes/blob/master/ansible /sacloud_inventory.py # kubespray実行イメージ # 環境変数でprofileとclusterを渡す $ USACLOUD_PROFILE=dev \ CLUSTER=@cluster=example \ ansible-playbook \ -i inventory/inventory.py \ -i inventory/prd.ini \ -e '@extra_vars_all.yml' \ --become --ask-pass --ask-become-pass \ kubespray/cluster.yml

Slide 51

Slide 51 text

事前準備 > sshconfig ● nodeにすぐログイン出来るようにsshconfigを自動生成できるようにしておくといい かも ● ということで便利ツールを作った ○ https://github.com/naoki912/example-sacloud-kubernetes/tree/master/utils 51

Slide 52

Slide 52 text

おまけ 52

Slide 53

Slide 53 text

そのた - うちのチームの過去の資料 ● Kubernetesって何ができるの?どうなってるの? ○ https://speakerdeck.com/amaya382/kubernetestutehe-gadekirufalse-dounatuterufalse ● Kubernetesを最大限に活かすためのGitOps入門 ○ https://speakerdeck.com/amaya382/kuberneteswozui-da-xian-nihuo-kasutamefalsegitopsru-men ● GitOpsでも秘匿情報をバッチリ扱う方法、SealedSecretとは? / How to manage credentials on GitOps ○ https://speakerdeck.com/amaya382/how-to-manage-credentials-on-gitops ● Kubernetes,Prometheusをやってみて辛い,辛かった話 / Prometheus's Experience ○ https://speakerdeck.com/takumanakagame/prometheuss-experience ● Prometheusを始めよう / Introduction Prometheus ja ○ https://speakerdeck.com/takumanakagame/introduction-prometheus-ja 53

Slide 54

Slide 54 text

sample project ● https://github.com/naoki912/example-sacloud-kubernetes/ ○ terraform project ○ Dynamic Inventory ○ ansible project ○ kubespray inventory ○ その他便利ツール 54