こしあん
2026-01-14

Kubernetes学習メモ(3)


6{icon} {views}

KCNA講座のSection 4に基づき、Docker Compose上のk3s環境を使ってPod・Deployment・Serviceなどの基本リソースをハンズオン形式で学習しました。 kubectlによるリソース作成やロールアウト管理に加え、ConfigMapやSecretsといった設定周りまで、Kubernetesの基礎的な操作手順を網羅的にまとめました。

これまでのもの

教材

今回はSection 4の内容

事前準備

Docker composeベースで動くハンズオンのラボがある。これを適当なLinux環境で実行しておく(ローカルでもEC2でもOK)

https://github.com/spurin/diveintokcna/tree/compose

※Docker Desktopなど様々な環境での実行に対応しているが、Staleされたブランチから切り替えるためどこにあるのか少しわかりづらいかも

クローン

git clone --single-branch -b compose https://github.com/spurin/diveintokcna.git
cd diveintokcna

環境立ち上げ

./start.sh

環境終了

./stop.sh

localhost:32535で、GUIベースのコンソールが出てくる。EC2の場合は、VSCodeが自動的にポートフォワードしてくれる。

コントロールプレーンで、ユーザー名root、パスワードrootでログインできる。

ただし、Kubectlのインストールが必要(Dockerなので毎回実行必要)

curl -sfLk https://get.k3s.io | INSTALL_K3S_VERSION=v1.31.0+k3s1 K3S_TOKEN=KCNA INSTALL_K3S_EXEC="--disable traefik --kubelet-arg=eviction-hard=imagefs.available<1%,nodefs.available<1%" sh -
mkdir -p ~/.kube; mv /etc/rancher/k3s/k3s.yaml ~/.kube/config

以下のコマンドが出ればKubectlが利用できる。

kubectl get nodes

worker1, 2のノードを追加する。全てコントロールプレーンで操作する

ssh worker-1 'curl -sfLk https://get.k3s.io | INSTALL_K3S_VERSION=v1.31.0+k3s1 K3S_URL=https://control-plane:6443 K3S_TOKEN=KCNA INSTALL_K3S_EXEC="--kubelet-arg=eviction-hard=imagefs.available<1%,nodefs.available<1%" sh -'

ssh worker-2 'curl -sfLk https://get.k3s.io | INSTALL_K3S_VERSION=v1.31.0+k3s1 K3S_URL=https://control-plane:6443 K3S_TOKEN=KCNA INSTALL_K3S_EXEC="--kubelet-arg=eviction-hard=imagefs.available<1%,nodefs.available<1%" sh -'

kubectl get nodesが以下のようになればOK

root@control-plane:~# kubectl get nodes
NAME            STATUS   ROLES                  AGE     VERSION
control-plane   Ready    control-plane,master   5m18s   v1.31.0+k3s1
worker-1        Ready    <none>                 92s     v1.31.0+k3s1
worker-2        Ready    <none>                 77s     v1.31.0+k3s1

Kubernetes Pod

nginxのPodを作成

kubectl run nginx --image=nginx

Podの一覧

kubectl get pods

Podのログ

kubectl logs pod/nginx

PodのIPを取得

kubectl get pods -o wide

接続テスト(IPが10.42.0.5と仮定)

ping 10.42.0.5

# 他のノードから
ssh worker-1 ping 10.42.0.5
ssh worker-2 ping 10.42.0.5

ポートフォワーディング

kubectl port-forward pod/nginx 8080:80

もう一個コントロールプレーンのシェルを開いて

curl 127.0.0.1:8080

# Welcome to nginxと表示される

Podの作成

kubectl run --image=ubuntu ubuntu sleep infinity

Ubuntu Podに接続(UbuntuのPod内に入れる)

kubectl exec -it ubuntu -- bash

Ubuntuからnginxへのアクセス

root@ubuntu:/# apt update
root@ubuntu:/# apt install curl

root@ubuntu:/# curl 10.42.0.5

Podの削除

kubectl delete pod/nginx pod/ubuntu --now

YAMLの自動作成

kubectl run nginx --image=nginx --dry-run=client -o yaml | tee nginx.yaml

命令型コマンド(Imperative):create, replace, delete
宣言型アプローチ(Declarative):apply

restartPolicyの列挙

kubectl explain pod.spec.restartPolicy

YAMLベースからのPodの作成

kubectl apply -f nginx.yaml

Ubuntuコンテナの作成

kubectl run --image=ubuntu --dry-run=client -o yaml ubuntu sleep infinity | tee ubuntu.yaml

kubectl apply -f ubuntu.yaml

2つのYAMLの結合(上のPodをDelete後)

{ cat nginx.yaml; echo "---"; cat ubuntu.yaml; } | tee combined.yaml

kubectl apply -f combined.yaml

YAMLベースのPodの削除

kubectl delete -f combined.yaml --now

サイドカー化(combined.yamlを編集)

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mypod
  name: mypod
spec:
  containers:
  - name: webserver
    image: nginx
    resources: {}
  - name: sidecar
    image: ubuntu
    args:
      - /bin/sh
      - -c
      - while true; do echo "$(date +'%T') - Hello from the sidecar"; sleep 5; if [ -f /tmp/crash ]; then exit 1; fi; done
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

curlのimagesを使ってnginxにリクエスト

kubectl apply -f combined.yaml
kubectl describe pod/mypod
# IPを確認する

kubectl run -it --rm --image=curlimages/curl --restart=Never curl -- http://<nginxのIP>

サイドカーのログを表示

kubectl logs pod/mypod -c sidecar

サイドカーコンテナをクラッシュさせる。kubectl get podsで再起動し、サイドカーのログを表示したときに新しくなっている。

kubectl exec -it mypod -c sidecar -- touch /tmp/crash

クラッシュ前のログの表示

kubectl logs pod/mypod -p -c sidecar

片付け

kubectl delete pod/mypod --now

Kubernetes Namespaces

全リソースの表示

kubectl get all -A

Namespaceの一覧(default, kube-system, kube-public, kube-node-leaseがある)

kubectl get namespaces

# または短縮形
kubectl get ns

短縮形のリスト

kubectl api-resources | more

Namespaceの作成

kubectl create namespace mynamespace

作成したNamespaceにPodを作成

kubectl -n mynamespace run nginx --image=nginx

指定したNamespaceのPod一覧

kubectl -n mynamespace get pods

デフォルトのNamespaceの確認(デフォルト:defaultのNS)

kubectl config view

デフォルトのNamespaceの切り替え(get podsなどでNamespaceを指定しなくてよくなる)

kubectl config set-context --current --namespace=mynamespace

デフォルトのNamespaceを戻す

kubectl config set-context --current --namespace=default

Namespaceの削除

kubectl delete namespace/mynamespace --now

Kubernetes Deployments and Replica sets

デプロイの作成(YAMLを仲介させる)

kubectl create deployment nginx --image=nginx --dry-run=client -o yaml | tee nginx-deployment.yaml | kubectl apply -f -

デプロイ一覧の取得

kubectl get deployment

ReplicaSetの一覧の取得

kubectl get replicasets

Podの確認

kubectl get pods -o wide

ロールアウトの履歴の取得

kubectl rollout history deployment/nginx

ロールアウトのメッセージを追加(rollout historyのメッセージが変わる)

kubectl annotate deployment/nginx kubernetes.io/change-cause="initial deployment"

デプロイの確認(Wideオプション)

kubectl get deployment -o wide

デプロイのスケールアウト

kubectl scale deployment/nginx --replicas=10; watch kubectl get pods -o wide

YAMLでReplica数を変更後反映する

kubectl apply -f nginx-deployment.yaml; watch kubectl get pods -o wide

デプロイの戦略をYAMLで見る

kubectl get deployment/nginx -o yaml | more

YAMLのimageをnginx:stableに変更したのち、ロールアウトを表示。ロールアウト後にkubectl get replicasetで古いReplicasetが0/0になっている。

kubectl apply -f nginx-deployment.yaml && kubectl rollout status deployment/nginx

ロールアウトのコメントをつける

kubectl annotate deployment/nginx kubernetes.io/change-cause="change imgae to nginx:stable"

kubectl rollout history deployment/nginx

コマンドラインからロールアウト

kubectl set image deployment/nginx nginx=nginx:alpine && kubectl rollout status deployment/nginx

kubectl annotate deployment/nginx kubernetes.io/change-cause="change imgae to nginx:alpine"

kubectl rollout history deployment/nginx

ロールアウト時のPodの様子

kubectl set image deployment/nginx nginx=nginx:perl && watch kubectl get pods -o wide

kubectl annotate deployment/nginx kubernetes.io/change-cause="change imgae to nginx:perl"

ロールアウト失敗時(存在しないタグを設定)。describe deploymentで古いReplicasetのIDが参照されているのがわかる。

kubectl set image deployment/nginx nginx=nginx:bananas && watch kubectl get pods -o wide

kubectl annotate deployment/nginx kubernetes.io/change-cause="change imgae to nginx:bananas - failed"

kubectl describe deployment/nginx

ロールアウトの巻き戻し(上のはImagePullBackOffをずっとやっている)。巻き戻し後はRevision 4がRevision 6になる。

kubectl rollout undo deployment/nginx && kubectl rollout status deployment/nginx

特定のリビジョンへの巻き戻し(rollout historyでは、リビジョンが2,3,5,6,7になっているはず)

kubectl rollout undo deployment/nginx --to-revision=1 && kubectl rollout status deployment/nginx

デプロイの削除

kubectl delete deployment/nginx --now

Kubernetes Services

デプロイの作成(nginxのデバッグ用のイメージ)

# YAML確認
kubectl create deployment nginx --image=spurin/nginx-debug --port 80 --replicas=3 -o yaml --dry-run=client

# 本番
kubectl create deployment nginx --image=spurin/nginx-debug --port 80 --replicas=3

ClusterIPとして公開

# YAML確認
kubectl expose deployment/nginx --dry-run=client -o yaml

# 本番
kubectl expose deployment/nginx

サービスの確認

kubectl get services

エンドポイントの一覧(get servicesと異なり複数IPが出る)

kubectl get endpoints

# 以下に対応
kubectl get pods -o wide

サービスの詳細。エンドポイントに対してcurl可能

kubectl describe service/nginx

curlimagesを使い、KubernetesのサービスのDNS経由でアクセスする

kubectl run --rm -it curl --image=curlimages/curl --restart=Never -- sh

# -- 以下コンテナ内のシェル操作--
curl nginx.default.svc.cluster.local

# デフォルトの検索パス(名前解決)の確認
cat /etc/resolv.conf

# サービス名でnginxでもアクセス可能
curl nginx

exit

NodePortとして公開する(いったんClusterIPは削除する)

kubectl delete service/nginx

kubectl expose deployment/nginx --type=NodePort

ClusterIPの場合、NodeのIPでアクセス可能(最初のコントロールプレーンのNodeのIPが172.19.0.4として)

# ポートの確認(80:30671でフォワードしているのを確認)
kubectl get services

# ノードのIPの確認(例:172.19.0.4)
kubectl get nodes -o wide

# ノードのIP+ポートでアクセス
curl 172.19.0.4:30671

ロードバランサーとして公開する(NodePortは削除)

kubectl delete service/nginx

kubectl expose deployment/nginx --type=LoadBalancer --port 8080 --target-port 80

以下のように出ていたと仮定

root@control-plane:~# kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                        PORT(S)          AGE
kubernetes   ClusterIP      10.43.0.1       <none>                             443/TCP          103m
nginx        LoadBalancer   10.43.225.134   172.19.0.2,172.19.0.3,172.19.0.4   8080:31868/TCP   7s

アクセス先の確認(ロードバランサーなので異なるPodに負荷分散されている)

watch --differences "curl 172.19.0.2:31868 2>/dev/null"

Podを1にスケールダウンした場合(worker-1,2がいる場合はバラけてしまうかも)

kubectl scale deployment/nginx --relicas=1; watch --differences "curl 172.19.0.2:31868 2>/dev/null"

スケールアップした場合

kubectl scale deployment/nginx --relicas=3; watch --differences "curl 172.19.0.2:31868 2>/dev/null"

クリーンアップ

kubectl delete deployment/nginx service/nginx

red blueの例の準備

kubectl create deployment nginx-red --image=spurin/nginx-red --port 80
kubectl create deployment nginx-blue --image=spurin/nginx-blue --port 80

kubectl get deployment

kubectl expose deployment/nginx-red
kubectl expose deployment/nginx-blue

DNSレコードの作成

kubectl create service externalname my-service --external-name nginx-red.default.svc.cluster.local

kubectl get service

curlのイメージで確認

kubectl run --rm -it curl --image=curlimages/curl --restart=Never -- sh

# 以下curlのコンテナ内
curl nginx-red
curl nginx-blue
curl my-service # red側になる

# my-service.default.svc.cluster.localが登録されている
nslookup my-service

サービスを編集し、DNSレコードをblue側に変える(別タブなど)

kubectl edit service/my-service

先程のcurl my-serviceを再実行すると、Blue側に変更されている(再起動必要なし)

クリーンアップ

kubectl delete deployment/nginx-blue deployment/nginx-red service/nginx-red service/nginx-blue service/my-service

ヘッドレス(ClusterIPを持たない)Podの作成。YAMLで書き出してspec以下にclusetrIP: Noneを追加する

kubectl create deployment nginx --image=spurin/nginx-debug --replicas=3 --port 80

kubectl expose deployment/nginx --dry-run=client -o yaml --type=ClusterIP | tee headless.yaml

vi headless.yaml

kubectl apply -f headless.yaml

# Cluster-IPがIPを持たない(None)になっている
kubectl get service

ヘッドレスの場合はIPが変わる

kubectl run --rm -it curl --image=curlimages/curl --restart=Never -- sh

# 以下curlコンテナ内の操作
# 実行のたびに変わる
watch nslookup nginx

curl nginx

クリーンアップ

rm headless.yaml

kubectl delete deployment/nginx service/nginx

Kubernetes Jobs

円周率を5000桁計算するジョブ

kubectl create job calculatepi --image=perl:5.34.0 -- "perl" "-Mbignum=bpi" "-wle" "print bpi(5000)"

ジョブの実行を完了するのをリアルタイムで見る

watch kubectl get jobs

ジョブの詳細を取得。完了時刻とか書いてある

kubectl describe job/calculatepi

実際に動いているPodの詳細

kubectl get pods -o wide

Podのログで計算された円周率を確認できる(実際のPod名に合わせる)

kubectl logs calculatepi-bmfzt 

ジョブの削除

kubectl delete job/calculatepi

YAMLに吐き出し

kubectl create job calculatepi --image=perl:5.34.0 --dry-run=client -o yaml -- "perl" "-Mbignum=bpi" "-wle" "print bpi(5000)" | tee calculatepi.yaml

KubernetesのJobの設定値を確認

kubectl explain job.spec | more

YAMLのSpecを編集する(completions=20とparallelism=5を追加)

apiVersion: batch/v1
kind: Job
metadata:
  creationTimestamp: null
  name: calculatepi
spec:
  completions: 20
  parallelism: 5
  template:
    metadata:
      creationTimestamp: null
    spec:
      containers:
      - command:
        - perl
        - -Mbignum=bpi
        - -wle
        - print bpi(5000)
        image: perl:5.34.0
        name: calculatepi
        resources: {}
      restartPolicy: Never
status: {}

並列化して実行してPodの様子を見る(同時には5しか実行されない)

kubectl apply -f calculatepi.yaml && sleep 1 && watch kubectl get pods -o wide

同様にログを見れる

kubectl delete job/calculatepi

cronjobに変えて毎分実行

kubectl create cronjob calculatepi --image=perl:5.34.0 --schedule="* * * * *" -- "perl" "-Mbignum=bpi" "-wle" "print bpi(2000)"

cronjobの一覧

kubectl get cronjob

毎分Podが立ち上がるのを確認

watch kubectl get pods

既存のCronjobのYAMLのSpecを編集する(同様にcompletions=20とparallelism=5を追加)

kubectl edit cronjob/calculatepi

リアルタイム確認

watch kubectl get jobs

クリーンアップ

kubectl delete cronjob/calculatepi
rm calculatepi.yaml

Kubernetes ConfigMaps

ConfigMapの作成

kubectl create configmap colour-configmap --from-literal=COLOUR=red --from-literal=KEY=value

ConfigMapの詳細(Key-Valueで出力される)

kubectl describe configmap/colour-configmap

ConfigMapの削除

kubectl delete configmap/colour-configmap

ファイルからのConfigMapの作成

cat <<EOF > configmap-colour.properties
> COLOUR=green
> KEY=value
> EOF

cat configmap-colour.properties

kubectl create configmap colour-configmap --from-env-file=configmap-colour.properties

ダンプ用のPodの作成

kubectl run --image=ubuntu --dry-run=client --restart=Never -o yaml ubuntu --command bash -- -c 'env; sleep infinity' | tee env-dump-pod.yaml

kubectl apply -f env-dump-pod.yaml

Pod内の環境変数のダンプ

kubectl get pods

kubectl logs ubuntu

これだと先ほど作成したConfigMapが含まれないので、YAMLを編集する(envFrom以下を追加)

vi env-dump-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
  name: ubuntu
spec:
  containers:
  - command:
    - bash
    - -c
    - env; sleep infinity
    image: ubuntu
    name: ubuntu
    resources: {}
    envFrom:
      - configMapRef:
          name: colour-configmap
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

ConfigMapの適用はPodの再作成が必要。これを実行するとCOLOUR=greenKEY=valueが登録されている。

kubectl delete -f env-dump-pod.yaml --now; kubectl apply -f env-dump-pod.yaml

kubectl logs ubuntu

値の変更(COLOUR=purple)に変えてみる(Podの再作成が必要)

kubectl edit configmap/colour-configmap

kubectl delete -f env-dump-pod.yaml --now; kubectl apply -f env-dump-pod.yaml

kubectl logs ubuntu

immutable:trueを追加すると値の変更ができなくなる(値を変更しようとするとエラーになる)。Kubernetes 1.21から。

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  COLOUR: purple
  KEY: value
immutable: true
kind: ConfigMap
metadata:                                  
  creationTimestamp: "2026-01-12T16:21:19Z"
  name: colour-configmap
  namespace: default     
  resourceVersion: "2175"                  
  uid: f98413d9-bc22-4b7e-8a9a-4fa5aef357d3

クリーンアップ

kubectl delete pod/ubuntu configmap/colour-configmap --now

rm configmap-colour.properties env-dump-pod.yaml

Kubernetes Secrets

シークレットの作成(YAMLで確認)

kubectl create secret generic colour-secret --from-literal=COLOUR=red --from-literal=KEY=value --dry-run=client -o yaml

シークレットがBase64エンコード値で記録されていることを確認(value=dmFsdWU=)として記録

# dmFsdWU=と表示される
echo -n value | base64

# valueとデコードされる
echo dmFsdWU= | base64 -d

シークレットの作成

kubectl create secret generic colour-secret --from-literal=COLOUR=red --from-literal=KEY=value

シークレットの一覧

kubectl get secrets

特定のシークレットの詳細をYAMLで確認

kubectl get secret/colour-secret -o yaml

ダンプ用のPodを起動するためのYAMLを作成

kubectl run --image=ubuntu --dry-run=client --restart=Never -o yaml ubuntu --command bash -- -c 'env; sleep infinity' | tee env-dump-pod.yaml

env-dum-pod.yamlを編集し、ConfigMapと同様にSecretsを登録

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
  name: ubuntu
spec:
  containers:
  - command:
    - bash
    - -c
    - env; sleep infinity
    image: ubuntu
    name: ubuntu
    resources: {}
    envFrom:
      - secretRef:
          name: colour-secret
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

環境変数のダンプ(base64ではなく、平文で記録されている)

kubectl logs ubuntu

クリーンアップ

kubectl delete pod/ubuntu secret/colour-secret --now

rm env-dump-pod.yaml

Kubernetes Labels

例えばPodを作るためのYAML

# labelsはnginxになることを確認
kubectl run nginx --image=nginx --port 80 -o yaml --dry-run=client 

kubectl run nginx --image=nginx --port 80

Portを公開

# labelがnginxになっていることを確認
kubectl expose pod/nginx -o yaml --dry-run=client

kubectl expose pod/nginx

ラベルがnginxのものを選択

kubectl get all --selector run=nginx

3つの異なるラベルのPodを作成

YAML=$(kubectl run --image=ubuntu ubuntu -o yaml --dry-run=client --command sleep infinity)
echo -e "${YAML}\n---\n${YAML}\n---\n${YAML}" | tee coloured_pods.yaml

YAMLのcolourラベルを追加し、名前を変える

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
    colour: red
  name: ubuntu-red
spec:
  containers:
  - command:
    - sleep
    - infinity
    image: ubuntu
    name: ubuntu
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
---
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
    colour: green
  name: ubuntu-green
spec:
  containers:
  - command:
    - sleep
    - infinity
    image: ubuntu
    name: ubuntu
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
---
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
    colour: pink
  name: ubuntu-pink
spec:
  containers:
  - command:
    - sleep
    - infinity
    image: ubuntu
    name: ubuntu
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Podの作成

kubectl apply -f coloured_pods.yaml

全Podの確認

kubectl get pods -o wide

色でセレクト

kubectl get all --selector colour=green

kubectl get all --selector colour=red

クリーンアップ

kubectl delete -f coloured_pods.yaml --now

kubectl delete pod/nginx --now

rm coloured_pods.yaml


Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です