LoginSignup
98
62

Kubernetes初心者向け:AWSを活用したコンテナ入門ハンズオン手順作ってみた

Last updated at Posted at 2022-01-30

職場で上記の勉強会を企画してみることにしたので、参加者むけの手順書を兼ねてやり方を残しておきます。

はじめに

こんな人向けのハンズオンです。

  • コンテナって興味あるけど自分で触ったことないからイメージわかない
  • Kubernetesに入門してみたい

必要なものは以下です。

  • PC:Win/Mac両対応。会社の業務OA端末(制限付きWindows)でも問題なし。
  • AWSアカウントとIAMユーザー:社内向けにはわたしの方で用意しました。

その1:ブラウザーでAWSログインして操作端末を起動

まずはウェブブラウザー(ChromeもしくはEdge推奨)を起動し、AWSの管理画面(マネジメントコンソール)にアクセスしてIAMユーザーでログインします。
 ※ 社内向けにはログイン用のURLとIAMユーザー認証情報を別紙でお渡しします。
スクリーンショット 2022-01-30 8.04.23a.png

新しいコンソールを使うか聞かれたら、どちらでもハンズオンに支障ないので好きな方を選びましょう。
スクリーンショット 2022-01-30 8.18.06.png

トップ画面が表示されたらログイン成功!
スクリーンショット 2022-01-30 8.19.43.png

次に、ハンズオン用の操作端末として利用する「CloudShell」サービスを起動します。
AWSマネジメントコンソール画面上部の検索窓に cloudshell と入力すると、サジェストが出てくるのでクリックしましょう。
スクリーンショット 2022-01-30 8.21.58.png

Welcomeポップアップは閉じてください。
スクリーンショット 2022-01-30 8.23.37.png

黒い画面が出現し、数秒待つと最下部にプロンプトが点滅してコマンドを打てるようになります。
今回このCloudShellを操作端末として使うので、制約の多い会社PCでもブラウザーさえ使えればハンズオンできちゃうというわけです。
スクリーンショット 2022-01-30 8.28.08.png

仮想ターミナルが準備完了し、カーソルがチカチカ点滅していることを確認したら、以下のコマンドをコピーしてCloudShellに貼り付け実行しましょう。
 ※ 環境準備はこちらの記事を参考にさせていただきました。

CloudShell
# ディレクトリ作成
mkdir -p $HOME/.local/bin
cd $HOME/.local/bin

# kubectl のインストール
curl -LO "https://dl.k8s.io/release/$(curl -LS https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl

# eksctl のインストール
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl $HOME/.local/bin

# ホームディレクトリに戻る
cd $HOME

コピペすると「こんなにまとめて貼り付けていいの?」って聞かれるので「Paste」ボタンをクリック。
スクリーンショット 2022-01-30 8.47.42.png

一連のコマンドがまとめて実行され、おそらく最後の行の cd $HOME にカーソルが残っていると思うので、Enterを押してこいつも実行します。
スクリーンショット 2022-01-30 8.50.54.png

これでCloudShell上に、Kubernetesのハンズオンに必要なツールをインストールできました。
次に以下のコマンドをCloudShellで実行して、EKSのクラスターを作成します。
 ※ 短いコマンドなので、できればコピペではなく自分で手入力してみましょう。その方が理解が深まります。

CloudShell
eksctl create cluster

これが完了まで20分ほどかかります。
裏ではCloudFormationというIaCツールが自動実行され、VPCやEC2などEKSクラスターに必要なインフラがもろもろ構築されていきます。

ここまで来たら、待ち時間のあいだに社内では「コンテナとは何ぞや?」的な紙芝居タイムに入ろうと思います。
 ※ 途中で詰まった方は講師がサポートしますので、遠慮なく発言したりチャット欄で教えてくださいね。

待ち時間:紙芝居タイム

コンテナって何?(Kubernetes入門)

これをやっている間に20分ぐらい経過してくれれば、EKSクラスターの作成が完了していると思います。
CloudShellに以下のような出力が表示され、プロンプトのカーソルが点滅して操作可能状態になっていればOKです。

CloudShell
2022-01-30 00:19:08 [✔]  EKS cluster "attractive-party-1643500815" in "ap-northeast-1" region is ready

ここに表示されている自分のEKSクラスター名はぜひ見ておいてください。マニアックな英語圏の動物名など、いろいろランダムで設定されるようです。
(eksctlでクラスター作成時、オプションを何も指定していないのでクラスター名やノード台数などはおまかせで自動設定されています)

※ CloudShellは一定時間操作しないでいると切断されてしまいます。
 が、Enterキーを入力すると数秒後にすぐ復帰しターミナル操作続行可能となります。

こいつをマネコンからも確認してみましょう。
CloudShellはそのままで、画面上部のAWSサービス検索ボックスに eks と入力するとEKSコンソールへのリンクが表示されます。
これを右クリックして「新しいタブで開く」と、CloudShellを開いたままEKSコンソールに移動できるので便利です。
スクリーンショット 2022-01-30 12.33.37.png

EKSコンソールの「クラスター」画面より、自分のクラスター名で検索してみるとちゃんと存在していることが分かると思います。
スクリーンショット 2022-01-30 12.38.40.png

クラスター名をクリックしてみると、ワーカーノード(データプレーンの土台部分のEC2)が一覧表示され、2台いることが分かります。
スクリーンショット 2022-01-30 12.41.14.png

ただし、AWSのマネコンからGUIで確認できる範囲はここまで!
ワーカーノード上で実際に動くコンテナの世界は、コマンドでしか見られないのでCloudShellに戻ります。

その2:いよいよK8sを触ってみる

サイボウズさんの新人研修資料が非常にわかりやすくて良かったので、今回テキストとして参考にさせていただきました。

上記資料のまんまMinikubeが使えると非常に楽なのですが、MinikubeはWindowsだと少々ややこしかったりPCの管理者権限も必要となるため、社内向けの勉強会では全員が同じ会社PC(制限付きWindows)でブラウザーから操作できるようAWSを活用してアレンジしてみたのが今回です。

この記事は以下出典のMITライセンスに基づいて公開しています。
Copyright (c) 2019 Cybozu
https://github.com/cybozu/introduction-to-kubernetes/blob/master/LICENSE

2-1. とりあえず現状を確認してみる

K8sの世界では「kubectl」というコマンドを使ってコンテナを操作します。
まずはデータプレーンのワーカーノードが何台いるのか確認してみましょう。
 ※ 短いコマンドなので、コピペではなく手打ちして理解を深めましょう。

CloudShell
kubectl get node

おそらく以下のような結果が出力されると思います。
さっきマネコンで見たとおり、EC2の名前が2台表示されてますね。

CloudShell
NAME                                                STATUS   ROLES    AGE    VERSION
ip-192-168-11-13.ap-northeast-1.compute.internal    Ready    <none>   3h6m   v1.21.5-eks-9017834
ip-192-168-72-188.ap-northeast-1.compute.internal   Ready    <none>   3h6m   v1.21.5-eks-9017834

さらに、Pod(コンテナ)はまだ何も作っていないはずですが、念のため一覧表示してみましょう。

CloudShell
kubectl get pod

「何もないよ」というメッセージだけが返ってきたと思います。
図にすると今こういう状態です。
スクリーンショット 2022-01-30 13.55.30.png

2-2. ドキドキ!はじめてのPodをデプロイしてみる

それではいよいよ自分の好きなアプリを入れたPod(コンテナ)を作成してみます。
Pod作成の注文は複雑になる(どんな名前にして、どんなコンテナイメージを使い、どんなスペックで動かすか…等)ので、ファミレスのようにオーダーを注文書に書いてからコントロールプレーンに指示します。

注文書はYAMLという形式のテキストファイルに書くルールになっています。
注文書のことを「マニフェスト」といいます。
 ※ YAMLは慣れないとビビりますが、中身はただのテキスト箇条書きなのでサルでも分かります。

最初は「NGINX」という代表的なWebサーバー製品をコンテナとして動かしてみたいと思います。
まずは以下のテキストをメモ帳にコピペして、「nginx-pod.yaml」という名前で会社PCのデスクトップに保存してみましょう。

nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
  labels:
    component: nginx 
spec:
  containers:
  - name: nginx 
    image: nginx:latest 

これだけで注文書は完成です。
NGINXは人気のOSSなので、すでに他の人が作って公開してくれているコンテナイメージが存在するため、注文書のなかでそれを流用するよう指定しています。

こいつをCloudShellから参照できるよう、アップロードします。
CloudShell画面右上の「Actions」より「Upload file」を選び、PCのデスクトップに保存した「nginx-pod.yaml」をアップロードします。
スクリーンショット 2022-01-30 13.00.42.png

アップロード完了したら、 ls コマンドを実行してCloudShellのカレントディレクトリー内を一覧表示してみましょう。自分が作ったYAMLファイルが表示されていればOKです。
スクリーンショット 2022-01-30 13.03.31.png

それでは、この注文書を使ってPodをデプロイしてみます。
コマンドは以下です。

CloudShell
kubectl apply -f nginx-pod.yaml

無事にPodが作成されたら、一覧表示して確認してみましょう。
先ほど打った以下コマンドをもう一度実行します。

CloudShell
kubectl get pod

すると以下のように、注文したとおり「my-nginx」というPodが1つ出現しています。
STATUSが「Running」なら、早くも起動終わって稼働中ということです。仮想マシン起動よりも断然早いのが分かります。

CloudShell
NAME       READY   STATUS    RESTARTS   AGE
my-nginx   1/1     Running   0          82s

ここまで図にするとこういう状態です。
スクリーンショット 2022-01-30 13.56.39.png

ちなみにPodの詳細表示をするコマンドは以下です。

CloudShell
kubectl describe pod my-nginx

打ってみるとPod名やIPアドレス、イベントログなど色々出力されるのが分かります。
Podの調子が悪い際はこうやってログなど確認します。

2-3. Podにログインしてみよう

Podのガワを見ているだけだと実感が湧かないので、Podにログインしてみましょう。
Pod内でコマンド実行できる kubectl exec を使ってbashを実行してみます。

CloudShell
kubectl exec -it my-nginx -- bash

これでPod内のOSをbashターミナルで操作できます。
図にするとこういう状態です。
スクリーンショット 2022-02-08 22.30.36.png

本当にPod内に入れているのか怪しいので、Pod内で自分に向かってcurlコマンドを打ってみましょう。
curlは雑に言うと、任意のURLへのHTTPアクセスをコマンド上で再現してくれる機能です。

CloudShell(my-nginx内)
curl localhost

だっと長めのテキストが出力されると思います。
CLIに慣れていない人はピンと来づらいと思いますが、今やってるのはGUIでいうと結局こういうことです。
スクリーンショット 2022-01-30 13.24.14.png

NGINXくんはWebサーバーなので、こういった画面を他の人が見られるように稼働してくれているわけですね。
curlの宛先にlocalhost(自分)を指定したらこのページが見られたので、ログインしているのは紛れもなくNGINX Podで正しかったということになります。

満足したら一旦 exit コマンドでmy-nginx Podから抜けて、CloudShellに戻ります。

2-4. Podから別のPodにアクセスしてみる

次は「CloudShellから直接Podを覗く」だけでなく、「Podからさらに別のPodへアクセスする」ことをしてみます。ようはサーバー間通信がちゃんとできるかの確認です。

まずは既存のNGINX Podと別に、踏み台用のLinux Podをデプロイしてみます。
以下をコピペして「fumidai-pod.yaml」を会社PCのデスクトップに保存して、先ほどと同様CloudShellにアップロードしてみてください。

fumidai-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: fumidai
spec:
  containers:
  - name: bastion
    image: debian:stable
    command: ["sleep", "infinity"]

Debianという種類のLinuxがインストールされただけのシンプルなPodです。
こいつをkubectlで追加デプロイしてみましょう。

CloudShell
kubectl apply -f fumidai-pod.yaml

デプロイできたら現在のPod一覧を確認してみましょう。
コマンドはそろそろ覚えてきたでしょうか?

CloudShell
NAME       READY   STATUS    RESTARTS   AGE
fumidai    1/1     Running   0          12s
my-nginx   1/1     Running   0          115m

踏み台くんが元気に追加されていますね。
ここまでこういう状態です。
スクリーンショット 2022-01-30 16.05.12.png

ただし正確に言うと、どのPodがどのノード(EC2)に乗っているかは不明です。
ノードとPodの管理はK8sにおまかせでよい世界で、あくまで利用者である僕らは「どんなPodが欲しいか」だけをオーダーしている状態です。

さて、踏み台Podにログインして、そこからNGINX Podへのアクセスを試してみたいのですが、その前に宛先となるNGINX PodのIPアドレスを確認しておく必要があります。
Pod一覧表示コマンドに -o wide オプションをつけるとIPアドレスも分かります。

CloudShell
kubectl get pod -o wide

NGINXのIPアドレスは分かったでしょうか。
それではまず踏み台Podへ kubectl exec でログインします。

CloudShell
kubectl exec -it fumidai -- bash

プロンプトが踏み台Linuxのrootに変わったら、お隣のmy-nginx PodにHTTPアクセスを試みましょう。
ただしcurlコマンドが未インストールのため、以下コマンドを実行して導入します。

CloudShell(fumidai内)
apt update
apt install -y curl

無事にcurlがインストールできたら、先ほど確認したmy-nginx PodのIPアドレス宛てに打ってみましょう。

CloudShell(fumidai内)
curl http://192.168.xx.xx

Welcome to nginx! ページは返ってきたでしょうか?
ここまで図にするとこういう状況です。
スクリーンショット 2022-02-08 22.30.44.png

ここまで成功したら、また exit コマンドで踏み台Podから抜けておきましょう。

2-5. 同用途のPodをたくさん増やして冗長化する

いまmy-nginx Podは1つだけですが、もしこいつに障害が起こったら誰も「Welcome to nginx!」ページを見られなくなってしまいます。
それは寂しくて困るので、このPodを常時3つ起動するよう注文書を書こうと思います。

先ほどまで書いていたYAMLは「Pod」という注文書ですが、Podを複数台セットで注文する場合は「レプリカセット」という別種の注文書を作る必要があります。
今回は「triple-nginx」という名前をレプリカセットに付けておきます。

nginx-replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: triple-nginx
  labels:
    component: nginx
spec:
  replicas: 3 
  selector: 
    matchLabels:
      component: nginx
  template: 
    metadata:
      labels:
        component: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest

こいつを「nginx-replicaset.yaml」ファイルとしてローカルに保存し、CloudShellにアップロードしましょう。
この注文書をデプロイする前に、まず現状のPod一覧を確認します。

CloudShell
kubectl get pod

最初にPodマニフェストでデプロイしたmy-nginx Podが1台と、踏み台が1台の計2台が存在していますね。
それでは、上記のレプリカセットを指定してPodをデプロイしてみましょう。

CloudShell
kubectl apply -f nginx-replicaset.yaml

すでにNGINXのPodが1つ存在するところに、NGINXを3つ動かしたいという注文書をオーダーしました。結果どうなるのか、 kubectl get pod コマンドで確認してみましょう。

CloudShell
NAME                 READY   STATUS              RESTARTS   AGE
fumidai              1/1     Running             0          48m
my-nginx             1/1     Running             0          164m
triple-nginx-gt89t   0/1     ContainerCreating   0          3s
triple-nginx-xfdqc   0/1     ContainerCreating   0          3s

すると上記のように、「triple-nginx」レプリカセットから生成された自動命名Podが2つ、追加で起動準備しているのが分かります。

なぜ既存の1台を同用途と認識できているかというと、最初にデプロイした「Pod」用マニフェストと今回の「Replicaset」マニフェストの両方とも、 component: nginx というラベルを仕込んでいました。
レプリカセットはこのラベルをもとにPodの稼働台数を見張る仕様になっているんですね。

nginx-replicaset.yaml
(前略)
metadata:
(中略)
  labels:
    component: nginx 
(後略)

ここまで図にするとこうなります。
スクリーンショット 2022-01-30 16.26.23.png

では、イタズラしてみましょう。
NGINXのPodを1台、わざと削除してやるとどうなるでしょうか。

CloudShell
kubectl delete pod my-nginx

Pod削除に成功したら、すかさず kubectl get pod でPod一覧を確認します。
すると、なんと「triple-nginx」レプリカセットから即座に1台、Podが追加生成されているのが分かります。

CloudShell
NAME                 READY   STATUS    RESTARTS   AGE
fumidai              1/1     Running   0          65m
triple-nginx-gt89t   1/1     Running   0          16m
triple-nginx-x2k5x   1/1     Running   0          4s
triple-nginx-xfdqc   1/1     Running   0          16m

ということで、Pod障害時の自動修復も超早いことが体感できたと思います。

2-6. 複数Podへロードバランスする

せっかく同用途のPodを3台に冗長化したので、PodへのアクセスもIPアドレス決め打ちではなく名前でアクセスできるようにしましょう。
そのためには「サービス」という新種の注文書を作ります。今回「my-nginx」という名前のサービスにします。

nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
spec:
  selector: 
    component: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

実はここにも component: nginx というラベルが仕込まれていることに気付いたでしょうか。
この「nginx-service.yaml」をまたCloudShellにアップロードして、デプロイしてみましょう。

CloudShell
kubectl apply -f nginx-service.yaml

この「サービス」もkubectlで一覧確認できます。
kubectl get service してみると、以下のようにデフォルトの「kubernetes」というサービスに加えて、いまデプロイした「my-nginx」サービスが動いていることが分かります。

それでは試しに踏み台PodからIPアドレス直指定ではなく、「my-nginx」サービス宛てにcurlでアクセスしてみましょう。

CloudShell
kubectl exec -it fumidai -- bash
curl http://my-nginx

Welcome to nginx! ページは返ってきたでしょうか?
これでNGINX PodをIP直指定ではなく、サービス名でロードバランスさせて裏のどれか1台にリクエストを返却させる、ということが可能になりました。
図にするとこうなります。
スクリーンショット 2022-01-30 16.53.05.png

ここまでできたら exit で踏み台Podから抜けておきましょう。

2-7. 複数Podをローリングアップデートしてみる

最後はちょっと難しい操作にチャレンジします。

いま「triple-nginx」レプリカセットではPod 3台が稼働していますが、開発チームがNGINXコンテナを更新したため、新しいPodへ置き換えたくなりました。
しかし Welcome to nginx! は24時間アクセスが止まない人気サイトのため、なるべく顧客影響ないよう1 Podずつこっそり更新したいです。

このときレプリカセットを使ってローリングアップデートしようとすると大変面倒です。
なぜなら、現新バージョンのレプリカセットを2つ作成し、新レプリカセットのPod台数を1台ずつチマチマ増やしつつ、同時に現行レプリカセットのPod台数を1台ずつチマチマ減らしていくという、何回 kubectl apply せなあかんねんという事態になります。

これを見越してK8sでは「デプロイメント」というレプリカセットの上位互換的な注文書も用意されています。(最初からそっち使えという話ですね)
「デプロイメント」では、同じ注文書のコンテナイメージ指定だけを新しいものに書き換えることで、勝手にPodを1台ずつ新パージョンのPodに置き換えてくれます。
スクリーンショット 2022-01-30 16.57.26.png

それではまず、ややこしいので下位互換の「レプリカセット」はいったん削除してしまいます。

CloudShell
kubectl delete replicaset triple-nginx

代わりに「デプロイメント」用のYAMLマニフェストを作成します。
現新2バージョン作っておき、両方ともCloudShellにアップロードしましょう。

「nginx-deployment-v1.yaml」(現行バージョン)
こちらはNGINX 1.20のコンテナイメージを指定しています。

nginx-deployment-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: triple-nginx
  labels:
    component: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20

「nginx-deployment-v2.yaml」(新バージョン)
こちらはNGINX 1.21のコンテナイメージを指定しています。

nginx-deployment-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: triple-nginx
  labels:
    component: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21

これら2つをCloudShellにアップロードできたら、まずは現行バージョンのデプロイメントを使ってPodをデプロイします。

CloudShell
kubectl apply -f nginx-deployment-v1.yaml

kubectl get pod してみると、NGINXのPodが3台起動していることが分かると思います。
この状態で新バージョンのデプロイメントを適用するとローリングアップデートが実施されます。

しかし、普通にやると経過がよく分からないので、CloudShellの別タブで踏み台Podにログインしておき、「my-nginx」サービスへNGINXのバージョン確認コマンドを0.1秒間隔で連打するよう仕込んでおきたいと思います。

まずCloudShell画面右上の「Action」ボタンより「New tab」をクリックします。
新しく開いたコンソールの方で、以下コマンドを実行し踏み台Podから確認コマンドを仕掛けます。

CloudShell(2タブ目)
kubectl exec -it fumidai -- bash
while true; do echo "-------"; date; curl -s -i my-nginx | grep -E 'Server'; sleep 0.1; done

nginx 1.20.2 という記載が確認できると思います。
ちなみにCloudShellの2タブ目は、画面右側にドラッグすると2つのタブを横並びで表示できるので便利です。
スクリーンショット 2022-01-30 17.26.55.png

このままCloudShellの1タブ目に戻り、新バージョン用のデプロイメントを適用してみましょう。

CloudShell(1タブ目)
kubectl apply -f nginx-deployment-v2.yaml

右側のCloudShellタブ上で、NGINXバージョンが少しずつ 1.21.6 へ置き換えられていくのが分かるんじゃないかと思います。
スクリーンショット 2022-01-30 17.27.48.png

通常、商用環境のK8sでPodをデプロイする際には、「Pod」や「レプリカセット」ではなくこの「デプロイメント」を利用するケースが一般的となるので覚えておきましょう。
(厳密に言うとデプロイメントを利用することにより、裏でよしなにレプリカセットがデプロイされ、さらにそのレプリカセットによりPodがデプロイされる…という風に下位オブジェクトをK8sが勝手にマネージしてくれます)

これであなたは、ローリング更新可能なNGINXコンテナを複数台、EKS環境上で稼働させる方法を習得できました!

おかたづけ

ムダなお金がかからないように、作ったクラスターを削除しましょう。
まずはクラスター名を確認して…

CloudShell
kubectl config get-clusters

最初のピリオドまでのカタマリがクラスター名です。
{12464D99-3378-4CFE-B5C0-744377021F23}.png.jpg
この部分を選択してコピーしたあと、以下の削除コマンドに埋め込んで投入しましょう。

CloudShell
eksctl delete cluster \
    --name 消したいクラスター名 \
    --wait

エラーでコケてしまった方は講師があとで消しておくので、諦めてそのまま放置でおkです。

まとめ

今回紹介した以下の「注文書(マニフェスト)」4種類によって定義されるものはそれぞれ、K8sの世界では「リソース」と表現します。

  • Pod
  • Replicaset
  • Deployment
  • Service

「リソース」はピンと来にくい表現なのですが、K8sの世界における「概念」のようなものです。
これらの「リソース」が実際に生成されたものを「オブジェクト」と言います。

私もまだまだKubernetes初心者なのですが、ここまで実機で触ってみていればコンテナ操作について何となくイメージが湧いてくるんじゃないかと思います。
こんなに分かりやすい新人研修資料を社外向けにも公開してくれたサイボウズさんには本当に感謝です!

※ 社内の勉強会においては、今回配布したIAMユーザーや作成いただいた各種AWSリソースは私のほうでまとめて削除しておきますのでご安心ください。

98
62
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
98
62