Open12

Kubernetes

jnstjnst

GKE

デフォルトリージョンとゾーンを設定

gcloud config list
 gcloud config set compute/region asia-northeast1
 gcloud config set compute/zone asia-northeast1-a

クラスタ作成

gcloud container clusters create --release-channel rapid --enable-ip-alias my-cluster
gcloud container clusters get-credentials my-cluster
kubectl config get-contexts
kubectl config current-context

クラスタ削除

gcloud container clusters delete my-cluster
jnstjnst

Pod が参照する DNS サーバーの設定4種類

ClusterFirst

  • デフォルト値
  • クラスター内部で解決できないときはノードの DNS サーバーで解決する
pod.yaml
spec:
  dnsPolicy: ClusterFirst

Default

  • ノードの DNS サーバーで解決する

ClusterFirstWithHostNet

  • hostNetwork を設定しているときに使う
pod.yaml
spec:
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

None

  • Kubernetes 環境の DNS 設定を無視する
  • 必ず dnsConfig フィールドの指定が必要
pod.yaml
spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 1.2.3.4
    searches:
      - ns1.svc.cluster.local
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0
jnstjnst

コマンド

名前空間を作成して ConfigMap にデータを格納する

kubectl create ns datatab
kubectl create cm my-config -n datatab --from-literal=confa=exvalue

ConfigMap から Pod の環境変数に値を格納する

$ kubectl run al-pod --image=redis --env=AL_USER=al-user --dry-run=client -o yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: al-pod
  name: al-pod
spec:
  containers:
  - env:
    - name: AL_USER
      value: al-user
    image: redis
    name: al-pod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

基本的な部分をファイル出力してから spec.containers.envvaluevalueFrom に書き換える

$ kubectl run al-pod --image=redis --env=AL_USER=al-user --dry-run=client -o yaml > al-pod.yaml
$ vi al-pod.yaml 
spec:
  containers:
  - env:
    - name: AL_USER
      valueFrom:
        configMapKeyRef:
          name: al-conf
          key: al-user

適用と確認

kubectl apply -f al-pod.yaml 
$ kubectl exec al-pod -- env | grep AL_USER
AL_USER=liptan

ちなみに kubectl exec al-pod -- echo $AL_USER ではシェルが違うため(?)確認できない

user と group を指定してコンテナを作成

$ kubectl run secure-pod --image=redis --dry-run=client -o yaml > secure-pod.yaml
$ vi secure-pod.yaml
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
$ kubectl apply -f secure-pod.yaml
$ kubectl exec secure-pod -- id
uid=1000 gid=2000 groups=2000

メモリ制限を Pod マニフェストを作成する

$ kubectl run limited-pod --image=busybox --requests=memory=100Mi --limits=memory=200Mi --dry-run=client -o yaml > /root/limited-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: limited-pod
  name: limited-pod
spec:
  containers:
  - image: busybox
    name: limited-pod
    resources:
      limits:
        memory: 200Mi
      requests:
        memory: 100Mi
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
jnstjnst

CKA by Killer Shell

current-context を取得

$ kubectl config current-context

kubectl を使わない方法

$ cat ~/.kube/config | grep -i current-context | awk '{print $2}'

Pod から ReplicaSet を特定する

$ kubectl get po o3db-0 -o yaml -n project-c13

metadata.ownerReferences を参照し kindname で特定する

metadata:
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: StatefulSet
    name: o3db
    uid: 6754662f-56d6-4d14-a0bc-b0a191d31c45
$ kubectl get statefulset -n project-c13
$ kubectl scale --replicas=1 -n project-c13 statefulset/o3db

Yaml の書き方を explain で調べる

$ kubectl explain pv.spec

Role と RoleBinding の作成

$ kubectl create role processor -n project-hamster --verb=create --resource=secrets,configmaps --dry-run=client -o yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: processor
  namespace: project-hamster
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  - configmaps
  verbs:
  - create
$ kubectl create rolebinding processor -n project-hamster --role=processor -dry-run=client -o yaml --serviceaccount=project-hamster:processor

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: processor
  namespace: project-hamster
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: processor
subjects:
- kind: ServiceAccount
  name: processor
  namespace: project-hamster

kube-scheduler を一時的に止める方法

/etc/kubernetes/manifests/kube-scheduler.yaml を上の階層等に移動する

jnstjnst

マスターノードに Pod をスケジュールする

マスターノードには taints が指定されているため、tolerations で容認する

$ kubectl describe node controlplane | grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  containers:
  - image: httpd:2.4.41-alpine
    name: pod1-container
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
  tolerations:
  - key: node-role.kubernetes.io/master
     operator: Equal
     value: ""
     effect: NoSchedule
  nodeSelector:
    node-role.kubernetes.io/master: ""
jnstjnst

これだけは気をつけるべき CKA

  • ~/.vimrc だけは必ず編集しておかないと k8s ドキュメントから YAML をコピペしたときに盛大にインデント崩れる
set tabstop=2
set expandtab
set shiftwidth=2
  • MacBook Air (Retina, 13-inch, 2020) 程度のスペックでサブディスプレイ使うとめちゃくちゃカクカクして vim 操作すら辛すぎて盛大に時間浪費する
    • MacBook だけで問題ない
    • あと tmux 使った方が効率的で有利になるかと思ったけどそうでもなかった
  • 最近 CKA に付属するようになった Killer Shell やりながらわからない知識を補完していけばなんとかなる
    • Udemy の Certified Kubernetes Administrator (CKA) with Practice Tests とか CKA 公式の KUBERNETES 基礎 (LFS258-JP) とかやらなくていい
      • 実技優先で覚えた方が時間対効果が高い
      • Kubernetes The Hard Way も試験には必要ない
    • ただし、通しで1回やるだけだと忘れてしまうので pod,deployment,svc,pv,pvc 等の主要な機能は数回やってドキュメント見ずともほぼほぼ書けるレベルになった方がいい
jnstjnst

混乱しやすいいろいろなポート

  • nodePort
    • 外部に公開するためのポート
    • svc.spec.typeNodePort を定義
    • svc.spec.ports.nodePort でポート番号の指定もできるが、デフォルトでは自動的に割り当てられる
  • port
    • NodePort で使われるサービスがリッスンするポート
  • targetPort
    • NodePort で使われる port が受信したトラフィックのリダイレクト先となるコンテナのポート
  • containerPort
    • Pod 上のコンテナにアクセスするためのポート
    • pod.spec.containers.ports.containerPort
jnstjnst

トラブルシューティング

  • アプリケーション障害
    • k logs <pod_name>
    • k get ev
    • k exec <pod_name>
  • コントロールプレーン障害
    • /etc/kubernetes/manifests
    • k -n kube-system logs <pod_name>
    • k -n kube-system logs kube-scheduler-$(hostname)
    • k -n kube-system get ev
    • systemctl
    • journalctl
    • systemctl status kubelet
    • journalctl -u kubelet | tail -5
  • ワーカーノード障害
    • kubectl get nodes
    • kubectl describe node <nodename>
    • service kubelet status
    • journalctl -u kubelet -f
  • ネットワーキング
    *
jnstjnst

Static Pod のつくり方

/etc/kubernetes/manifests にマニフェストを置けば kubelet によって作成される

$ cd /etc/kubernertes/manifests
$ kubectl run my-static-pod \
  --image=nginx:1.16-alpine \
  --requests "cpu=10m,memory=20Mi" \
  -o yaml --dry-run=client > my-static-pod.yaml
$ k get po -A | grep my-static-pod
default       my-static-pod-controlplane                 1/1     Running            0          7m48s
jnstjnst

etcd バックアップのための認証情報の取得方法

$ cat /etc/kubernetes/manifests/etcd.yaml | grep -e key-file -e cert-file -e ca-file
    - --cert-file=/etc/kubernetes/pki/etcd/server.crt
    - --key-file=/etc/kubernetes/pki/etcd/server.key
    - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
    - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
    - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
$ ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /tmp/etcd-backup.db
jnstjnst

ワーカーノードのアップグレード

マスターノード/ワーカーノードのそれぞれでバージョン確認

$ kubeadm version
$ kubectl version
$ kubelet --version

インストール

$ apt-get update
$ apt-get install kubectl=1.22.1-00 kubelet=1.22.1-00
$ systemctl restart kubelet
$ service kubelet status
jnstjnst

ワーカーノードをクラスターに参加させる

マスターノード

$ kubeadm token create --print-join-command

出力結果をワーカーノードで実行