Kubernetes the hard way (GCP版)の続きです。
前回の記事はこちら
Chap13. Smake Test(スモークテスト)
Chap12まででクラスターに関連する設定を一通り行いました。
このチャプターではクラスターが正常に動作しているかを確認するために、一連のタスクを実施します。
一部の作業ログが欠落しているので、手順の内容をそのまま記載している部分もありますがご了承下さい。
データの暗号化
Kubernetesで利用可能なリソースの一種であるSecretの暗号化機能を確認します。
SecretはKubernetesクラスター内で機密情報を管理するためのリソースとして利用されます。
データはControl Plane上のetcdに保管されるので、セキュリティの観点ではetcdの暗号化が必須になります。
最初に、機密情報のKey-Valueのペアを--from-literal
で渡して検証用のSecretを作成します。
渡した値は自動的にBase64でencodeされます。
~/w/k/h/04 ❯❯❯ kubectl create secret generic kubernetes-the-hard-way \ --from-literal="mykey=mydata" secret/kubernetes-the-hard-way created ~/w/k/h/04 ❯❯❯ k get secrets NAME TYPE DATA AGE default-token-bn72d kubernetes.io/service-account-token 3 178m kubernetes-the-hard-way Opaque 1 14s
Secretの作成後に、Control Planeにログインしてetcd内のデータを確認します。
作成したSecret名を用いてディレクトリ(/registry/secrets/default/kubernetes-the-hard-way
)を指定して、Key, Valueを取得します。
さらに取得したデータをhexdump
コマンドを利用して16進数とASCII文字でダンプします。
etcd上のデータにはk8s:enc:aescbc:v1:key1
が付与されており、aescbcプロバイダがキー(key1)のデータを暗号化するために使用されたことを示しています。
~/w/k/h/04 ❯❯❯ gcloud compute ssh controller-0 \ --command "sudo ETCDCTL_API=3 etcdctl get \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/etcd/ca.pem \ --cert=/etc/etcd/kubernetes.pem \ --key=/etc/etcd/kubernetes-key.pem\ /registry/secrets/default/kubernetes-the-hard-way | hexdump -C" Enter passphrase for key '/Users/nishikawatakushi/.ssh/google_compute_engine': 00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret| 00000010 73 2f 64 65 66 61 75 6c 74 2f 6b 75 62 65 72 6e |s/default/kubern| 00000020 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d 77 61 |etes-the-hard-wa| 00000030 79 0a 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 |y.k8s:enc:aescbc| 00000040 3a 76 31 3a 6b 65 79 31 3a 4e ed 61 e8 69 49 fa |:v1:key1:N.a.iI.| 00000050 19 c2 58 32 f3 7b 5b 7b f6 2b 67 0e af de a7 0c |..X2.{[{.+g.....| 00000060 d6 cf 48 b2 e2 7a 2d 44 9d 19 f8 06 8b e8 3d 74 |..H..z-D......=t| 00000070 89 eb 0e ba d4 ec b8 78 0b 84 b0 01 12 83 18 72 |.......x.......r| 00000080 c8 1e a6 25 a7 ca aa c5 a8 3a 0a f4 59 fa 2d 1d |...%.....:..Y.-.| 00000090 03 54 5b 08 62 c6 5e b1 da 02 1b a6 ab 8f d6 c3 |.T[.b.^.........| 000000a0 ea c6 69 56 53 93 68 b4 29 93 df 21 79 36 1d dd |..iVS.h.)..!y6..| 000000b0 d3 05 fa fd c5 40 d2 d5 4b e8 c8 da 48 60 3e 6b |.....@..K...H`>k| 000000c0 29 33 6b 4a 9f f3 1b 8a 02 da 00 45 cd 93 98 ce |)3kJ.......E....| 000000d0 ac cc d7 a4 a6 93 e0 ae 1d bc 9c 1b 7c e3 c0 ef |............|...| 000000e0 c9 b6 4e 7a 6f 46 41 12 0e 0a |..NzoFA...| 000000ea
Deploymentの作成
次にWorkloadsリソースの1種であるDeploymentを作成します。
kubectl create
コマンドを利用することで、マニュフェストファイルを事前に用意することなく作成することが可能です。
$ kubectl create deployment nginx --image=nginx $ kubectl get pods -l app=nginx NAME READY STATUS RESTARTS AGE nginx-554b9c67f9-vt5rn 1/1 Running 0 10s
ポートフォワーディング
作成したDeployment(pod)に対して、ポートフォワーディングを行いクラスタ内のコンテナへアクセスします。
今回はnginxのコンテナを作成しているので、コンテナの80番ポートにアクセスします。
~/w/k/h/04 ❯❯❯ POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}") ~/w/k/h/04 ❯❯❯ kubectl port-forward $POD_NAME 8080:80 Forwarding from 127.0.0.1:8080 -> 80 Forwarding from [::1]:8080 -> 80 ~/w/k/h/04 ❯❯❯ kubectl port-forward $POD_NAME 8080:80 Forwarding from 127.0.0.1:8080 -> 80 Forwarding from [::1]:8080 -> 80 Handling connection for 8080 ~~~~~~~ ~ ❯❯❯ curl --head http://127.0.0.1:8080 HTTP/1.1 200 OK Server: nginx/1.17.8 Date: Sat, 29 Feb 2020 07:28:01 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 21 Jan 2020 13:36:08 GMT Connection: keep-alive ETag: "5e26fe48-264" Accept-Ranges: bytes
ログ出力
作成したPodに対して、標準出力からPodのログをダンプします。
(この部分は作業ログが無かったため、手順の内容をそのまま記載しています。)
手順の中では標準出力の内容を直接取得していますが、実際の運用では標準出力・標準エラー出力をログファイルに書き出してロギング用のAgentを用いて転送したり、sidecarを用いたり様々なケースが考えられます。
こういったロギングの方法については、 Kubernetesの公式ドキュメントにまとめられています。
$ kubectl logs $POD_NAME 127.0.0.1 - - [14/Sep/2019:21:10:11 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.52.1" "-"
コンテナ内でのコマンド実行
docker exec
コマンドと同様に、Kubernetesでも作成したコンテナ上でコマンドを実行することが可能です。
今回はnginxのバージョンを確認するコマンドを実行します。
$ kubectl exec -ti $POD_NAME -- nginx -v nginx version: nginx/1.17.3
Serviceを用いたアプリケーションの実行
最後に、Serviceを作成してクラスタ外部から作成したコンテナにアクセスできるようにします。
kubectl expose
コマンドを用いて、事前に作成したDeploymentに紐付ける形でServiceを作成します。
$ kubectl expose deployment nginx --port 80 --type NodePort $ NODE_PORT=$(kubectl get svc nginx \ --output=jsonpath='{range .spec.ports[0]}{.nodePort}')
次に、払い出されたNodePortのポート番号(NODE_PORT
)でアクセスできるようにGCPのFirewall Ruleでアクセスできるように修正します。
$ gcloud compute firewall-rules create kubernetes-the-hard-way-allow-nginx-service \ --allow=tcp:${NODE_PORT} \ --network kubernetes-the-hard-way
最後にNode(GCE)自体のIPアドレスを取得して、curlコマンドを実行します。
正常に設定が行われていれば、ポートフォワーディングの際と同じようなレスポンスが返ってくるはずです。
$ EXTERNAL_IP=$(gcloud compute instances describe worker-0 \ --format 'value(networkInterfaces[0].accessConfigs[0].natIP)') $ curl -I http://${EXTERNAL_IP}:${NODE_PORT} HTTP/1.1 200 OK Server: nginx/1.17.3 Date: Sat, 14 Sep 2019 21:12:35 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 13 Aug 2019 08:50:00 GMT Connection: keep-alive ETag: "5d5279b8-264" Accept-Ranges: bytes
今回は、Chap13の内容をまとめました。
これにて、Kubernetes the hard wayのブログシリーズは終了です。
(Chap14は作成したリソース類の削除なので、ブログ記事の作成は行いません。)
機会があれば、AWS, Azure版など他のクラウドでのHard wayや手順を一部変更した改造版などを実施してみようと思います。