kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

今更ながらkOpsを使ってみる

f:id:kun432:20210120011530p:plain

kubeadm、EKS、GKE、kindといろいろ触ってきましたが、少しkOpsも触ってみようと思います。

目次

準備

kopsをインストールします。MacならHomebrewで。

$ brew install kops

$ kops version
Version 1.22.0

_r sshの鍵を作っておきます。nodeにsshするのに必要になります。~/.ssh/id_rsa、~/.ssh/id_rsa.pubがデフォルトで使用されるようです。こちらの環境だけなのかもですが、明示的に指定しないと公開鍵が設定されていませんでした。記事最後の補足を参照してください。

$ ssh key-gen

S3のバケットを作成します。ここがTerraformでいうところのtfstateの保存場所みたいなものになり、ここにクラスタの状態が保存されるようです。バケット名はkops-sample-202110としました。バージョニングと暗号化を有効にしておきます。

$ aws s3 mb s3://kops-sample-202110 

$ aws s3api put-bucket-versioning --bucket kops-sample-202110 --versioning-configuration Status=Enabled

$ aws s3api put-bucket-encryption --bucket kops-sample-202110 --server-side-encryption-configuration '{
    "Rules": [
        {
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            }
        }
    ]
}'

順番が前後しましたが、IAMの権限は適宜設定しておく必要があります。

バケットを環境変数KOPS_STATE_STOREに設定しておきます。環境変数に設定しておくとkopsコマンドが自動で読み込んでくれます(そうでない場合は--stateで指定する必要があります。)

$ export KOPS_STATE_STORE=s3://kops-sample-202110

クラスタ作成

kops create clusterでクラスタを作成します。まずはdry-runしてみましょう。

$ kops create cluster \
  --name kops-sample.k8s.local \
  --zones "ap-northeast-1a,ap-northeast-1c,ap-northeast-1d" \
  --master-zones "ap-northeast-1a" \
  --dry-run \
  --output=yaml

--nameでクラスタ名を指定します。クラスタ名の末尾を"k8s.local"にしておくと、ノード間通信においてGossipプロトコルを使って名前解決できるように構築してくれます。そうでない場合はRoute53での名前解決となり、少し準備が必要みたいです。

--zones、--master-zonesでそれぞれworkerノード、masterノードが配置されるAZを指定する感じですね。

--dry-runと--outputを組み合わせると、こんな感じでkopsクラスタの構築を行うためのmanifestが出力されます。

apiVersion: kops.k8s.io/v1alpha2
kind: Cluster
metadata:
  creationTimestamp: null
  name: kops-sample.k8s.local
spec:
  api:
    loadBalancer:
      class: Classic
      type: Public
  authorization:
    rbac: {}
  channel: stable
  cloudProvider: aws
  configBase: s3://kops-sample-202110/kops-sample.k8s.local
  etcdClusters:
  - cpuRequest: 200m
    etcdMembers:
    - encryptedVolume: true
      instanceGroup: master-ap-northeast-1a
      name: a
    memoryRequest: 100Mi
    name: main
  - cpuRequest: 100m
    etcdMembers:
    - encryptedVolume: true
      instanceGroup: master-ap-northeast-1a
      name: a
    memoryRequest: 100Mi
    name: events
  iam:
    allowContainerRegistry: true
    legacy: false
  kubelet:
    anonymousAuth: false
  kubernetesApiAccess:
  - 0.0.0.0/0
  - ::/0
  kubernetesVersion: 1.22.2
  masterPublicName: api.kops-sample.k8s.local
  networkCIDR: 172.20.0.0/16
  networking:
    kubenet: {}
  nonMasqueradeCIDR: 100.64.0.0/10
  sshAccess:
  - 0.0.0.0/0
  - ::/0
  subnets:
  - cidr: 172.20.32.0/19
    name: ap-northeast-1a
    type: Public
    zone: ap-northeast-1a
  - cidr: 172.20.64.0/19
    name: ap-northeast-1c
    type: Public
    zone: ap-northeast-1c
  - cidr: 172.20.96.0/19
    name: ap-northeast-1d
    type: Public
    zone: ap-northeast-1d
  topology:
    dns:
      type: Public
    masters: public
    nodes: public

---

apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: kops-sample.k8s.local
  name: master-ap-northeast-1a
spec:
  image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20211001
  instanceMetadata:
    httpPutResponseHopLimit: 3
    httpTokens: required
  machineType: t3.medium
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: master-ap-northeast-1a
  role: Master
  subnets:
  - ap-northeast-1a

---

apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: kops-sample.k8s.local
  name: nodes-ap-northeast-1a
spec:
  image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20211001
  instanceMetadata:
    httpPutResponseHopLimit: 1
    httpTokens: required
  machineType: t3.medium
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: nodes-ap-northeast-1a
  role: Node
  subnets:
  - ap-northeast-1a

---

apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: kops-sample.k8s.local
  name: nodes-ap-northeast-1c
spec:
  image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20211001
  instanceMetadata:
    httpPutResponseHopLimit: 1
    httpTokens: required
  machineType: t3.medium
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: nodes-ap-northeast-1c
  role: Node
  subnets:
  - ap-northeast-1c

---

apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: kops-sample.k8s.local
  name: nodes-ap-northeast-1d
spec:
  image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20211001
  instanceMetadata:
    httpPutResponseHopLimit: 1
    httpTokens: required
  machineType: t3.medium
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: nodes-ap-northeast-1d
  role: Node
  subnets:
  - ap-northeast-1d

master x 1、worker x 3のクラスタができるようですね。また、オプションで指定したとおり、workerは各AZごとに配置されています。

で、実際にクラスタを作る場合は--dry-runを外して--yesをつければよいですが、これだとコード管理できません。

$ kops create cluster \
  --name kops-sample.k8s.local \
  --zones "ap-northeast-1a,ap-northeast-1c,ap-northeast-1d" \
  --master-zones "ap-northeast-1a" \
  --yes

ということで、最初に実行したようにmanifestをファイルに出力してこれをgitで管理すればよいですね。あわせてクラスタ名も環境変数に入れておきましょう。

$ export KOPS_CLUSTER_NAME=kops-sample.k8s.local

$ kops create cluster \
  --name $KOPS_CLUSTER_NAME \
  --zones "ap-northeast-1a,ap-northeast-1c,ap-northeast-1d" \
  --master-zones "ap-northeast-1a" \
  --dry-run \
  --output=yaml > cluster.yaml

manifestから作成する場合はこうなります。

$ kops create -f cluster.yaml

Created cluster/kops-sample.k8s.local
Created instancegroup/master-ap-northeast-1a
Created instancegroup/nodes-ap-northeast-1a
Created instancegroup/nodes-ap-northeast-1c
Created instancegroup/nodes-ap-northeast-1d

To deploy these resources, run: kops update cluster --name kops-sample.k8s.local --yes

これでS3にkopsの設定が保存されます。まだAWS側にリソースは作成されていません。

$ aws s3 ls $KOPS_STATE_STORE --recursive
2021-10-20 01:59:16       1392 kops-sample.k8s.local/config
2021-10-20 01:59:16        527 kops-sample.k8s.local/instancegroup/master-ap-northeast-1a
2021-10-20 01:59:17        523 kops-sample.k8s.local/instancegroup/nodes-ap-northeast-1a
2021-10-20 01:59:17        523 kops-sample.k8s.local/instancegroup/nodes-ap-northeast-1c
2021-10-20 01:59:17        523 kops-sample.k8s.local/instancegroup/nodes-ap-northeast-1d

$ aws ec2 describe-instances
{
    "Reservations": []
}

リソースの作成はkops update clusterになります。ここもまずはdry-runしてみましょう。

$ kops update cluster

作成されるリソースが表示されます。初回は結構なボリュームになりますので詳細は割愛しますが、VPC、Autoscaling Group、ELBなどがまるっと作成されます。

(snip)
Will create resources:
  AutoscalingGroup/master-ap-northeast-1a.masters.kops-sample.k8s.local
    Granularity             1Minute
    InstanceProtection      false
    LaunchTemplate          name:master-ap-northeast-1a.masters.kops-sample.k8s.local
    LoadBalancers           [name:api.kops-sample.k8s.local id:api.kops-sample.k8s.local]
    MaxSize                 1
    Metrics                 [GroupDesiredCapacity, GroupInServiceInstances, GroupMaxSize, GroupMinSize, GroupPendingInstances, GroupStandbyInstances, GroupTerminatingInstances, GroupTotalInstances]
    MinSize                 1
    Subnets                 [name:ap-northeast-1a.kops-sample.k8s.local]
    SuspendProcesses        []
    Tags                    {kops.k8s.io/instancegroup: master-ap-northeast-1a, Name: master-ap-northeast-1a.masters.kops-sample.k8s.local, k8s.io/cluster-autoscaler/node-template/label/kops.k8s.io/kops-controller-pki: , k8s.io/cluster-autoscaler/node-template/label/kops.k8s.io/instancegroup: master-ap-northeast-1a, k8s.io/cluster-autoscaler/node-template/label/kubernetes.io/role: master, k8s.io/cluster-autoscaler/node-template/label/node.kubernetes.io/exclude-from-external-load-balancers: , KubernetesCluster: kops-sample.k8s.local, kubernetes.io/cluster/kops-sample.k8s.local: owned, k8s.io/cluster-autoscaler/node-template/label/node-role.kubernetes.io/control-plane: , k8s.io/cluster-autoscaler/node-template/label/node-role.kubernetes.io/master: , k8s.io/role/master: 1}
    TargetGroups            []

  AutoscalingGroup/nodes-ap-northeast-1a.kops-sample.k8s.local
    Granularity             1Minute
    InstanceProtection      false
    LaunchTemplate          name:nodes-ap-northeast-1a.kops-sample.k8s.local
    LoadBalancers           []
    MaxSize                 1

(snip)

  WarmPool/nodes-ap-northeast-1c.kops-sample.k8s.local
    Enabled                 false
    MinSize                 0

  WarmPool/nodes-ap-northeast-1d.kops-sample.k8s.local
    Enabled                 false
    MinSize                 0

Must specify --yes to apply changes

実際に作成する場合は--yesをつけて実行します。

$ kops update cluster --yes

I1020 02:16:04.464719   10704 apply_cluster.go:486] Gossip DNS: skipping DNS validation
I1020 02:16:05.438371   10704 executor.go:111] Tasks: 0 done / 109 total; 45 can run
W1020 02:16:05.689388   10704 vfs_castore.go:377] CA private key was not found
I1020 02:16:05.721809   10704 keypair.go:213] Issuing new certificate: "apiserver-aggregator-ca"
I1020 02:16:05.722095   10704 keypair.go:213] Issuing new certificate: "etcd-peers-ca-main"
I1020 02:16:05.752876   10704 keypair.go:213] Issuing new certificate: "etcd-manager-ca-events"
I1020 02:16:05.755179   10704 keypair.go:213] Issuing new certificate: "etcd-manager-ca-main"
I1020 02:16:05.759375   10704 keypair.go:213] Issuing new certificate: "etcd-clients-ca"
I1020 02:16:05.759390   10704 keypair.go:213] Issuing new certificate: "etcd-peers-ca-events"
W1020 02:16:05.860249   10704 vfs_castore.go:377] CA private key was not found
I1020 02:16:05.895603   10704 keypair.go:213] Issuing new certificate: "service-account"
I1020 02:16:05.902369   10704 keypair.go:213] Issuing new certificate: "kubernetes-ca"
I1020 02:16:06.982864   10704 executor.go:111] Tasks: 45 done / 109 total; 20 can run
I1020 02:16:08.345336   10704 executor.go:111] Tasks: 65 done / 109 total; 28 can run
I1020 02:16:10.324305   10704 executor.go:111] Tasks: 93 done / 109 total; 4 can run
I1020 02:16:10.534874   10704 executor.go:111] Tasks: 97 done / 109 total; 8 can run
I1020 02:16:11.526088   10704 executor.go:111] Tasks: 105 done / 109 total; 4 can run
I1020 02:16:12.875095   10704 executor.go:155] No progress made, sleeping before retrying 4 task(s)
I1020 02:16:22.878792   10704 executor.go:111] Tasks: 105 done / 109 total; 4 can run
I1020 02:16:24.920557   10704 executor.go:111] Tasks: 109 done / 109 total; 0 can run
I1020 02:16:24.969647   10704 update_cluster.go:326] Exporting kubeconfig for cluster
kOps has set your kubectl context to kops-sample.k8s.local
W1020 02:16:25.252095   10704 update_cluster.go:350] Exported kubeconfig with no user authentication; use --admin, --user or --auth-plugin flags with `kops export kubeconfig`

Cluster is starting.  It should be ready in a few minutes.

Suggestions:
 * validate cluster: kops validate cluster --wait 10m
 * list nodes: kubectl get nodes --show-labels
 * ssh to the master: ssh -i ~/.ssh/id_rsa ubuntu@api.kops-sample.k8s.local
 * the ubuntu user is specific to Ubuntu. If not using Ubuntu please use the appropriate user based on your OS.
 * read about installing addons at: https://kops.sigs.k8s.io/operations/addons.

作成が開始されました。完了までには少し時間がかかりますので、しばらく経ってから上記出力されている通り確認してみましょう。なお、KUBECONFIGもこの時点でセットされています。

$ kops validate cluster --wait 10m
Validating cluster kops-sample.k8s.local

INSTANCE GROUPS
NAME            ROLE    MACHINETYPE MIN MAX SUBNETS
master-ap-northeast-1a  Master  t3.medium   1   1   ap-northeast-1a
nodes-ap-northeast-1a   Node    t3.medium   1   1   ap-northeast-1a
nodes-ap-northeast-1c   Node    t3.medium   1   1   ap-northeast-1c
nodes-ap-northeast-1d   Node    t3.medium   1   1   ap-northeast-1d

NODE STATUS
NAME                            ROLE    READY
ip-172-20-114-156.ap-northeast-1.compute.internal   node    True
ip-172-20-52-226.ap-northeast-1.compute.internal    node    True
ip-172-20-56-170.ap-northeast-1.compute.internal    master  True
ip-172-20-77-187.ap-northeast-1.compute.internal    node    True

Your cluster kops-sample.k8s.local is ready

$ kubectl get nodes
NAME                                                STATUS   ROLES                  AGE   VERSION
ip-172-20-114-156.ap-northeast-1.compute.internal   Ready    node                   14m   v1.22.2
ip-172-20-52-226.ap-northeast-1.compute.internal    Ready    node                   14m   v1.22.2
ip-172-20-56-170.ap-northeast-1.compute.internal    Ready    control-plane,master   16m   v1.22.2
ip-172-20-77-187.ap-northeast-1.compute.internal    Ready    node                   14m   v1.22.2

クラスタが動作していますね。何かしらデプロイしてみましょう。

$ kubectl create deployment nginx --image=nginx
$ kubectl create service loadbalancer nginx --tcp=80:80
$ kubectl get all
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-6799fc88d8-zdwz9   1/1     Running   0          13m

NAME                 TYPE           CLUSTER-IP     EXTERNAL-IP                                                                  PORT(S)        AGE
service/kubernetes   ClusterIP      100.64.0.1     <none>                                                                       443/TCP        59m
service/nginx        LoadBalancer   100.71.13.67   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXX.ap-northeast-1.elb.amazonaws.com   80:30641/TCP   13m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           13m

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-6799fc88d8   1         1         1       13m

serviceに表示されているELBのDNS名にアクセスできればOKです。

クラスタの設定変更

クラスタの設定変更は2つの方法があるようです。

  • kops editで変更、kops updateで反映
  • kops replace で 変更済manifestを適用する

manifestをコード管理するのであれば後者が良いですね。ということで少し修正してみましょう。worker nodeの設定のmaxSize/minSIzeを変更して増やします。今回は3AZにしたのでAZごとに3箇所あります。

(snip)
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: kops-sample.k8s.local
  name: nodes-ap-northeast-1a
spec:
  image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20211001
  instanceMetadata:
    httpPutResponseHopLimit: 1
    httpTokens: required
  machineType: t3.medium
  maxSize: 2   ★
  minSize: 2   ★
  nodeLabels:
    kops.k8s.io/instancegroup: nodes-ap-northeast-1a
  role: Node
  subnets:
  - ap-northeast-1a
(snip)

変更をS3上にまず反映します。

$ kops replace -f cluster.yaml

反映します。まずはdry-runから。

$ kops update cluster

(snip)

Will modify resources:
  AutoscalingGroup/nodes-ap-northeast-1a.kops-sample.k8s.local
    MaxSize                  1 -> 2
    MinSize                  1 -> 2

  AutoscalingGroup/nodes-ap-northeast-1c.kops-sample.k8s.local
    MaxSize                  1 -> 2
    MinSize                  1 -> 2

  AutoscalingGroup/nodes-ap-northeast-1d.kops-sample.k8s.local
    MaxSize                  1 -> 2
    MinSize                  1 -> 2

(snip)

Must specify --yes to apply changes

nodeが増えるということがわかりますね。では反映しましょう。

$ kops update cluster --yes

確認してみます。

$ kops validate cluster
Validating cluster kops-sample.k8s.local

INSTANCE GROUPS
NAME            ROLE    MACHINETYPE MIN MAX SUBNETS
master-ap-northeast-1a  Master  t3.medium   1   1   ap-northeast-1a
nodes-ap-northeast-1a   Node    t3.medium   2   2   ap-northeast-1a
nodes-ap-northeast-1c   Node    t3.medium   2   2   ap-northeast-1c
nodes-ap-northeast-1d   Node    t3.medium   2   2   ap-northeast-1d

NODE STATUS
NAME                            ROLE    READY
ip-172-20-114-156.ap-northeast-1.compute.internal   node    True
ip-172-20-52-226.ap-northeast-1.compute.internal    node    True
ip-172-20-56-170.ap-northeast-1.compute.internal    master  True
ip-172-20-77-187.ap-northeast-1.compute.internal    node    True

VALIDATION ERRORS
KIND    NAME            MESSAGE
Machine i-054dfeb9d396bd9ba machine "i-054dfeb9d396bd9ba" has not yet joined cluster
Machine i-06556522774c42413 machine "i-06556522774c42413" has not yet joined cluster
Machine i-0b561cb80abe171f3 machine "i-0b561cb80abe171f3" has not yet joined cluster

Validation Failed
Error: Validation failed: cluster not yet healthy

新しいnodeが3台追加されましたがまだクラスタには登録されていないようです。この時点ではkubectl get nodeでも表示されません。しばらく待つとこうなります。

$ kops validate cluster
Validating cluster kops-sample.k8s.local

INSTANCE GROUPS
NAME            ROLE    MACHINETYPE MIN MAX SUBNETS
master-ap-northeast-1a  Master  t3.medium   1   1   ap-northeast-1a
nodes-ap-northeast-1a   Node    t3.medium   2   2   ap-northeast-1a
nodes-ap-northeast-1c   Node    t3.medium   2   2   ap-northeast-1c
nodes-ap-northeast-1d   Node    t3.medium   2   2   ap-northeast-1d

NODE STATUS
NAME                            ROLE    READY
ip-172-20-114-156.ap-northeast-1.compute.internal   node    True
ip-172-20-122-241.ap-northeast-1.compute.internal   node    True
ip-172-20-52-226.ap-northeast-1.compute.internal    node    True
ip-172-20-56-170.ap-northeast-1.compute.internal    master  True
ip-172-20-61-191.ap-northeast-1.compute.internal    node    True
ip-172-20-77-187.ap-northeast-1.compute.internal    node    True
ip-172-20-89-255.ap-northeast-1.compute.internal    node    True

Your cluster kops-sample.k8s.local is ready

$ kubectl get node
NAME                                                STATUS   ROLES                  AGE   VERSION
ip-172-20-114-156.ap-northeast-1.compute.internal   Ready    node                   74m   v1.22.2
ip-172-20-122-241.ap-northeast-1.compute.internal   Ready    node                   41s   v1.22.2
ip-172-20-52-226.ap-northeast-1.compute.internal    Ready    node                   74m   v1.22.2
ip-172-20-56-170.ap-northeast-1.compute.internal    Ready    control-plane,master   76m   v1.22.2
ip-172-20-61-191.ap-northeast-1.compute.internal    Ready    node                   54s   v1.22.2
ip-172-20-77-187.ap-northeast-1.compute.internal    Ready    node                   74m   v1.22.2
ip-172-20-89-255.ap-northeast-1.compute.internal    Ready    node                   41s   v1.22.2

もう一つ別のパターンの変更も行ってみましょう。

先程はworker nodeを追加しました。つまり既存のworker nodeには特に変更はありません。既存のリソースに対する変更はローリングアップデートが必要になります。インスタンスタイプの変更で試してみましょう。

(snip)
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: kops-sample.k8s.local
  name: nodes-ap-northeast-1a
spec:
  image: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20211001
  instanceMetadata:
    httpPutResponseHopLimit: 1
    httpTokens: required
  machineType: t3.large  ★
  maxSize: 2
  minSize: 2
  nodeLabels:
    kops.k8s.io/instancegroup: nodes-ap-northeast-1a
  role: Node
  subnets:
  - ap-northeast-1a
(snip)

先ほどと同じようにreplaceしてupdateして確認します。

$ kops replace -f cluster.yaml
$ kops update cluster

Will modify resources:
  LaunchTemplate/nodes-ap-northeast-1a.kops-sample.k8s.local
    InstanceType             t3.medium -> t3.large

  LaunchTemplate/nodes-ap-northeast-1c.kops-sample.k8s.local
    InstanceType             t3.medium -> t3.large

  LaunchTemplate/nodes-ap-northeast-1d.kops-sample.k8s.local
    InstanceType             t3.medium -> t3.large

Must specify --yes to apply changes

反映します。

$ kops update cluster --yes
(snip)
Cluster changes have been applied to the cloud.


Changes may require instances to restart: kops rolling-update cluster

クラスタの設定は変更されていますが、既存のnodeはまだ置き換わっていません。kops rolling-updateしてみます。もちろんdry-runで。

$ kops rolling-update cluster
NAME            STATUS      NEEDUPDATE  READY   MIN TARGET  MAX NODES
master-ap-northeast-1a  Ready       0       1   1   1   1   1
nodes-ap-northeast-1a   NeedsUpdate 2       0   2   2   2   2
nodes-ap-northeast-1c   NeedsUpdate 2       0   2   2   2   2
nodes-ap-northeast-1d   NeedsUpdate 2       0   2   2   2   2

Must specify --yes to rolling-update.

各nodeでアップデートが必要となっていますね。ではローリングアップデートします。

$ kops rolling-update cluster --yes
NAME            STATUS      NEEDUPDATE  READY   MIN TARGET  MAX NODES
master-ap-northeast-1a  Ready       0       1   1   1   1   1
nodes-ap-northeast-1a   NeedsUpdate 2       0   2   2   2   2
nodes-ap-northeast-1c   NeedsUpdate 2       0   2   2   2   2
nodes-ap-northeast-1d   NeedsUpdate 2       0   2   2   2   2
I1020 03:47:05.474509   14129 instancegroups.go:470] Validating the cluster.
I1020 03:47:06.664522   14129 instancegroups.go:503] Cluster validated.
I1020 03:47:06.664548   14129 instancegroups.go:306] Tainting 2 nodes in "nodes-ap-northeast-1a" instancegroup.
I1020 03:47:07.020806   14129 instancegroups.go:568] Detaching instance "i-XXXXXXXXXXXX71f3", node "ip-172-20-61-191.ap-northeast-1.compute.internal", in group "nodes-ap-northeast-1a.kops-sample.k8s.local".
I1020 03:47:07.477186   14129 instancegroups.go:167] waiting for 15s after detaching instance
I1020 03:47:22.482042   14129 instancegroups.go:470] Validating the cluster.
I1020 03:47:24.200364   14129 instancegroups.go:526] Cluster did not pass validation, will retry in "30s": machine "i-XXXXXXXXXXXX0367" has not yet joined cluster
(snip)

新しいec2インスタンスが作成され、古いものが削除される感じで、更新されていきます。台数が多いとそれなりに時間かかります。なお、podはevictされて別のnodeに移ります。

ローリングアップデートが完了するとこうなります。

$ kops rolling-update cluster
NAME            STATUS  NEEDUPDATE  READY   MIN TARGET  MAX NODES
master-ap-northeast-1a  Ready   0       1   1   1   1   1
nodes-ap-northeast-1a   Ready   0       2   2   2   2   2
nodes-ap-northeast-1c   Ready   0       2   2   2   2   2
nodes-ap-northeast-1d   Ready   0       2   2   2   2   2

No rolling-update required.

クラスタの削除

削除はkops delete clusterで。dry-runから。

$ kops delete cluster

TYPE            NAME                            ID
autoscaling-config  master-ap-northeast-1a.masters.kops-sample.k8s.local    lt-XXXXXXXXXXXXXXXX
autoscaling-config  nodes-ap-northeast-1a.kops-sample.k8s.local     lt-XXXXXXXXXXXXXXXX
autoscaling-config  nodes-ap-northeast-1c.kops-sample.k8s.local     lt-XXXXXXXXXXXXXXXX
autoscaling-config  nodes-ap-northeast-1d.kops-sample.k8s.local     lt-XXXXXXXXXXXXXXXX
(snip)

Must specify --yes to delete cluster

削除対象のリソースが表示されます。問題なければ削除します。

$ kops delete cluster --yes

補足

nodeにsshするために鍵を作っていましたが、実際にはログインできず。instance connectでつないでみるとautorized_keysが空になっていました。以下のように実行すると設定できましたが、これだけでrolling-updateが必要になるのは微妙ですね。

$ kops create secret --name ${KOPS_CLUSTER_NAME} sshpublickey admin -i ~/.ssh/id_rsa.pub
$ kops update cluster --yes
$ kops rolling-update cluster --yes

クラスタmanifest作成時に明示的に指定してあげることができるっぽいけど。

$ kops create cluster \
  --name $KOPS_CLUSTER_NAME \
  --zones "ap-northeast-1a,ap-northeast-1c,ap-northeast-1d" \
  --master-zones "ap-northeast-1a" \
  --ssh-public-key ~/.ssh/id_rsa.pub \
  --dry-run \
  --output=yaml > cluster.yaml

こんな感じで出力されてるのでいけてそうにみえるけど。

I1020 11:35:17.386822   17947 create_cluster.go:827] Using SSH public key: /Users/kun432/.ssh/id_rsa.pub

やっぱりauthorized_keysは空だった。多分kops create clusterで直接クラスタ作成すればできるんだろうけど、manifest作ってからkops create -fする場合は、manifestには何も記載がないし、kops create -f --ssh-public-keyは指定できないっぽいので、作成されないんだと思います。

manifestベースでやるとするならば事前にキーペアを作っておいて、manifest内でキーペア名を指定するのが良さそうかなと。

$ aws ec2 create-key-pair --key-name kops-sample-202110 --query 'KeyMaterial' --output text > kops-sample.pem
$ chmod 600 kops-sample.pem
$ kops create cluster \
  --name $KOPS_CLUSTER_NAME \
  --zones "ap-northeast-1a" \
  --master-zones "ap-northeast-1a" \
  --dry-run \
  --output=yaml > cluster.yaml

Clusterリソースのspec.sshKeyNameでキーペア名を追記。

apiVersion: kops.k8s.io/v1alpha2
kind: Cluster
metadata:
  creationTimestamp: null
  name: kops-sample.k8s.local
spec:
  sshKeyName: kops-sample-202110

あとはこれでクラスタ作ればOK。authorized_keysに公開鍵が含まれていることを確認できました。

まとめ

kopsで構築されたクラスタを触ったことはあるけど、ちゃんと理解してなかったので一通り触れてみて雰囲気をつかめたのがよかったです。manifestでコード管理できるのもよいですし、あと、今回はVPCから作成しましたが、既に存在するVPCのリソース上に作成することもできるみたいなので、追加導入もしやすそうですね。

参考