Skip to content

Instantly share code, notes, and snippets.

@yhirano55
Last active September 26, 2023 15:01
Show Gist options
  • Save yhirano55/a948922c17ef05c33dfd32b7b2aca64c to your computer and use it in GitHub Desktop.
Save yhirano55/a948922c17ef05c33dfd32b7b2aca64c to your computer and use it in GitHub Desktop.
katacoda

なぜKubernetesが必要なのか?

https://thinkit.co.jp/article/13289

k8sとは

  • Kubernetesはコンテナ化されたアプリケーションの展開、スケーリング、および管理を自動化するためのコンテナオーケストレーションエンジンです。
  • Dockerに注目が集まり、プロダクションで利用するシーンが増えたため、あと、Microservices化などの流れに伴って、流行している。
  • 以前はDocker Swarmもあったが、デファクトスタンダードはk8sになっている。

マネージドKubernetes

  • GCP: Google Container Engine(GKE)
  • Azure: Azure Container Service(AKS)
  • AWS: Amazon Elastic Container Service for Kubernetes(EKS)

Dockerをプロダクションで利用する場合に考えなければならないこと

  • 複数のDockerホストの管理
  • コンテナのスケジューリング
  • ローリングアップデート
  • スケーリング / オートスケーリング
  • コンテナの死活監視
  • 障害時のセルフヒーリング
  • サービスディスカバリ
  • ロードバランシング
  • データの管理
  • ワークロードの管理
  • ログの管理
  • Infrastructure as Code
  • その他エコシステムとの連携や拡張

K8sでできること

  • YAMLのマニフェストファイルで、実行コンテナなど宣言的に記述できる(Infrastructure as a Code: devOps)
  • Kubernetesは、複数のDockerホストを管理してコンテナクラスタを構築します。また、コンテナをKubernetes上で実行する際には、同じコンテナのレプリカとして展開することで負荷分散や耐障害性の確保をすることが可能です。さらに負荷に応じて、コンテナのレプリカ数を増減(オートスケーリング)することもできます。

Kubernetes環境の選択肢

https://thinkit.co.jp/article/13338

3つの選択肢

  • 手元のWindows/Mac上でローカル Kubernetes 環境を立ち上げる
  • 構築ツールを使ってクラスタを構築する
  • パブリッククラウドのマネージド Kubernetes を利用する

マネージドサービスを使うのが一般的!?

  • ローカルKubernetes
    • Minikube
    • Docker for Mac
  • Kubernetes構築ツール
    • kubeadm
    • Rancher
  • パブリッククラウド上のマネージドKubernetes
    • Google Kubernetes Engine(GKE)
    • Azure Container Service(AKS)
    • Elastic Container Service for Kubernetes(EKS)

Minikube

  • ローカルで動かす場合に使われることが多い。
  • デフォルトでVirtual Boxが必要。

Docker for Mac

  • Preferencesから、Kubernetesを有効化すれば利用できる(起動まで5分ほどかかる)
  • Minikubeを利用している場合は、コンテキストを切り替える必要がある。 $ kubectl config use-context docker-for-desktop

Kubernetesの基礎

https://thinkit.co.jp/article/13542

KubernetesはKubernetes MasterとKubernetes Nodeから成り立っている

  • Kubernetes MasterはAPIエンドポイントの提供、コンテナのスケジューリング、コンテナのスケーリングなどを担います。
  • Kubernetes Nodeは、いわゆるDocker Hostに相当する実際にコンテナが起動するホストです。
  • kubectlも内部でKubernetes MasterのAPIを叩いているだけなので、ライブラリやcurlなどでも操作することが可能です。

Kubernetesとリソース

  • Kubernetes では「リソース」を登録することで、非同期にコンテナの実行やロードバランサの作成が行われます。
  • リソースにはコンテナ、ロードバランサ、ノードなど様々な種類があり、リソースによってYAMLマニフェストに指定できるパラメータが異なります。
リソースの分類 内容
Workloadsリソース コンテナの実行に関するリソース
Discovery&LBリソース コンテナを外部公開するようなエンドポイントを提供するリソース
Config&Storageリソース 設定・機密情報・永続化ボリュームなどに関するリソース
Clusterリソース セキュリティやクォータなどに関するリソース
Metadataリソース リソースを操作する系統のリソース

Workloads リソース

クラスタ上にコンテナを起動させるのに利用するリソースです。内部的に利用されているものを除いて利用者が直接利用するものとしては、全部で8種類のWorkloadsリソースが存在します。

  • Pod
  • ReplicationController
  • ReplicaSet
  • Deployment
  • DaemonSet
  • StatefulSet
  • Job
  • CronJob

Discovery&LBリソース

2つ目のDiscovery&LBリソースは、コンテナのサービスディスカバリや、外部からもアクセス可能なエンドポイントなどを提供するリソースです。

  • Service
    • ClusterIP
    • NodePort
    • LoadBalancer
    • ExternalIP
    • ExternalName
    • Headless
  • Ingress

Config&Storageリソース

3つ目のConfig&Storageリソースは、設定や機密データをコンテナに埋め込んだり、永続ボリュームを提供するリソースです。

  • Secret
  • ConfigMap
  • PersistentVolumeClaim

Clusterリソース

4つ目のClusterリソースは、クラスタ自体の振る舞いを定義するリソースです。

  • Namespace
  • ServiceAccount
  • Role
  • ClusterRole
  • RoleBinding
  • ClusterRoleBinding
  • NetworkPolicy
  • ResourceQuota
  • PersistentVolume
  • Node

Metadataリソース

5つ目のMetadataリソースは、クラスタ内の他のリソースの動作を制御するようなリソースです。

  • CustomResourceDefinition
  • LimitRange
  • HorizontalPodAutoscaler

kubectlの使い方

  1. nginxの起動
  2. ログの確認
  3. コンテナ内にttyで接続

KubernetesのWorkloadsリソース(その1)

https://thinkit.co.jp/article/13610

Pod

  • Workloads リソースの最小単位
  • 1つ以上のコンテナから構成
  • ネットワークは隔離されておらず、IP Addressなどは共有しています。
  • コンテナ単位でIPアドレスが割り当てられるわけではなく、Pod単位でIPアドレスが割り当てられる。
  • 多くの場合は、1Pod1コンテナを含むが、Proxyの役割をするコンテナ、設定値の動的な書き換えを行うコンテナ、ローカルキャッシュ用のコンテナ、SSL終端用のコンテナなどをPod内に入れておくことで2コンテナ以上を内包したPodが利用されることも。
  • 補助するサブコンテナのことを「サイドカー」と呼ぶ。
apiVersion: v1
kind: Pod
metadata:
  name: sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
      ports:
      - containerPort: 80

複数コンテナの場合:

apiVersion: v1
kind: Pod
metadata:
  name: sample-2pod
spec:
  containers:
    - name: nginx-container-112
      image: nginx:1.12
      ports:
      - containerPort: 80
    - name: nginx-container-113
      image: nginx:1.13
      ports:
      - containerPort: 8080

コンテナへのログイン

$ kubectl exec -it sample-pod /bin/bash

ReplicaSet (ReplicationController)

  • ReplicaSetはPodのレプリカを生成し、指定した数のPodを維持し続けるリソースです。
  • ReplicationControllerは今後廃止の流れになっている。

Deployment

  • 複数のReplicaSetを管理することで、ローリングアップデートやロールバックなどを実現可能にするリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.12
          ports:
            - containerPort: 80

KubernetesのWorkloadsリソース(その2)

https://thinkit.co.jp/article/13611

DaemonSet

  • ReplicaSetの特殊な形ともいえるリソース
  • DaemonSetは、全nodeに1 podずつ配置するリソース
  • レプリカ数などは指定できませんし、2 podずつ配置するといったこともできません。

StatefulSet

  • データベースなどstatefulなワークロードに対応するためのリソース
  • 生成されるPod名が数字でindexingされたものになる
  • 永続化するための仕組みを有している
    • PersistentVolumeを使っている場合は同じディスクを利用して再作成される
    • Pod名が変わらない

Job

  • コンテナを利用して一度限りの処理を実行させるリソース
  • 並列実行なども行いながら、指定した回数までコンテナの実行(正常終了)が保証されるリソース
  • バッチ的な処理の場合にはJobを積極的に利用しましょう。
apiVersion: batch/v1
kind: Job
metadata:
  name: sample-job
spec:
  completions: 1
  parallelism: 1
  backoffLimit: 10
  template:
    spec:
      containers:
      - name: sleep-container
        image: centos:latest
        command: ["sleep"]
        args: ["60"]
      restartPolicy: Never

CronJob

  • Jobに似たリソース
  • Kubernetes 1.4までScheduledJobという名前でしたが、CronJobに名称が変更になった。
  • Cronのようにスケジュールされた時間にJobを生成します。
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: sample-cronjob
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 30
  successfulJobsHistoryLimit: 5
  failedJobsHistoryLimit: 5
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: sleep-container
            image: centos:latest
            command: ["sleep"]
            args: ["30"]
          restartPolicy: Never

まとめ

  • 基本的にはPodやReplicaSetを使うようなケースはDeploymentを使っておいたほうが良いでしょう。
  • 細かい仕様の差はさておき、この8個のWorkloadsリソースは把握しておく必要があります。

Launch Single Node Kubernetes Cluster

Step 1. Start Minikube

Minikubeのバージョンチェック

$ minikube version

クラスターの起動

$ minikube start

Step 2. Cluster Info

クラスターの状態を確認

$ kubectl cluster-info
Kubernetes master is running at https://172.17.0.22:8443

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

ノードの状態を確認

$ kubectl get nodes
NAME       STATUS    ROLES     AGE       VERSION
minikube   Ready     <none>    3m        v1.10.0

Step 3. Deploy Containers

kubectl run でclusterにイメージをデプロイする

$ kubectl run first-deployment --image=katacoda/docker-http-server --port=80
deployment.apps "first-deployment" created

デプロイ後の状態確認は以下

$ kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
first-deployment-59f6bb4956-gnmsv   1/1       Running   0          1m

コンテナに動的なポートを割り当てる

$ kubectl expose deployment first-deployment --port=80 --type=NodePort
service "first-deployment" exposed

外部にEXPOSEしたポートを確認して、HTTPリクエストを送ってみると

$ export PORT=$(kubectl get svc first-deployment -o go-template='{{range.spec.ports}}{{if .nodePort}}{{.nodePort}}{{"\n"}}{{end}}{{end}}')
$ echo "Accessing host01:$PORT"
Accessing host01:31636
$ curl host01:$PORT
<h1>This request was processed by host: first-deployment-59f6bb4956-gnmsv</h1>

Step 4. Dashboard

$ minikube dashboard

Start containers using Kubectl

Kubectlを利用してコンテナを立ち上げる

Step 1 - Launch Cluster

クラスタを立ち上げると、VMが起動してIPアドレスの割り当て等を行い、kubectlが利用できるようになる。

$ minikube start
There is a newer version of minikube available (v0.28.2).  Download it here:
https://github.com/kubernetes/minikube/releases/tag/v0.28.2

To disable this notification, run the following:
minikube config set WantUpdateNotification false
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

ノードを確認すると、Readyだとわかる

$ kubectl get nodes
NAME       STATUS    ROLES     AGE       VERSION
minikube   Ready     <none>    2m        v1.10.0

Step 2 - Kubectl Run

runコマンドは、指定されたパラメータ(イメージやreplicaなど)に基づいてデプロイメントを作成する。デプロイメントは、k8sのマスターでポッドとコンテナが起動される。docker runと似ている。フォーマットは kubectl run <name of deployment> <properties> となる。

以下は、httpというデプロイメントを起動するタスク

$ kubectl run http --image=katacoda/docker-http-server:latest --replicas=1
deployment.apps "http" created

起動後にデプロイメントの状態を確認すると

$ kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
http      1         1         1            1           56s

デプロイメントの詳細な情報をみる場合は、 describe サブコマンドを利用する

$ kubectl describe deployment http
Name:                   http
Namespace:              default
CreationTimestamp:      Sat, 28 Jul 2018 07:59:33 +0000
Labels:                 run=http
Annotations:            deployment.kubernetes.io/revision=1
Selector:               run=http
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  run=http
  Containers:
   http:
    Image:        katacoda/docker-http-server:latest
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   http-7b77c4cd66 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  1m    deployment-controller  Scaled up replica set http-7b77c4cd66 to 1

Step 3 - Kubectl Expose

kubectlを使用して、特定のポート上のPodを公開するサービスを作成することができます。

新しくデプロイされたhttpデプロイメントをkubectl公開経由で公開します。このコマンドを使用すると、サービスのさまざまなパラメータを定義し、展開を公開する方法を指定できます。

次のコマンドを使用して、ホスト8000​​のコンテナポート80をホストのexternal-ipにバインドします。

$ kubectl expose deployment http --external-ip="172.17.0.30" --port=8000 --target-port=80
service "http" exposed

サービスの状態を確認する

$ kubectl get service
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
http         ClusterIP   10.107.198.109   172.17.0.30   8000/TCP   50s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    11m

HTTPリクエストを送るとレスポンスが返ります。

$ curl http://172.17.0.30:8000
<h1>This request was processed by host: http-7b77c4cd66-5fl44</h1>

Step 4 - Kubectl Run and Expose

これまでのステップは、1コマンドで可能です。

$ kubectl run httpexposed --image=katacoda/docker-http-server:latest --replicas=1 --port=80 --hostport=8001
deployment.apps "httpexposed" created

内部ではDockerのポートマッピングを利用している?

Step 5 - Scale Containers

デプロイメントを実行すると、kubectlを使用してレプリカの数を調整できます。deploymentを増やすと、Kubernetesに追加のPodを起動するよう要求されます。これらのポッドは、公開されたサービスを使用して自動的に負荷分散されます。

以下では、httpという命名のデプロイメントを3つ複製している

$ kubectl scale --replicas=3 deployment http
deployment.extensions "http" scaled

以下でPodが増えたことが確認できる

$ kubectl get pods

Deploy Containers Using YAML

YAMLの設定ファイルとkubectlでデプロイメントやレプリケーションコントローラーを作成・公開できる。

Step 1 - Create Deployment

以下 deployment.yml として保存。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: webapp1
    spec:
      containers:
      - name: webapp1
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80

設定ファイルを適用する

$ kubectl create -f deployment.yaml
deployment.extensions "webapp1" created

詳細を確認する

$ kubectl describe deployment webapp1
Name:                   webapp1
Namespace:              default
CreationTimestamp:      Sat, 28 Jul 2018 08:33:35 +0000
Labels:                 app=webapp1
Annotations:            deployment.kubernetes.io/revision=1
Selector:               app=webapp1
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=webapp1
  Containers:
   webapp1:
    Image:        katacoda/docker-http-server:latest
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   webapp1-6c66d9cb4f (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  23s   deployment-controller  Scaled up replica set webapp1-6c66d9cb4f to 1

Step 2 - Create Service

Kubernetesには、アプリケーションの通信方法を制御する強力なネットワーク機能があります。これらのネットワーク構成は、YAMLを介して制御することもできます。

apiVersion: v1
kind: Service
metadata:
  name: webapp1-svc
  labels:
    app: webapp1
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30080
  selector:
    app: webapp1

適用する

$ kubectl create -f service.yaml
service "webapp1-svc" created

状態を確認する

$ kubectl get svc
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP        10m
webapp1-svc   NodePort    10.97.163.118   <none>        80:30080/TCP   20s

詳細を確認する

$ kubectl describe svc webapp1-svc
Name:                     webapp1-svc
Namespace:                default
Labels:                   app=webapp1
Annotations:              <none>
Selector:                 app=webapp1
Type:                     NodePort
IP:                       10.97.163.118
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                172.18.0.4:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Step 3 - Scale Deployment

外部にサービスが公開されたので、スケールさせる。deployment.ymlのreplicasの値を増やせばよいので、値を変更し、適用させ、deploymentを確認する

$ kubectl apply -f deployment.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment.extensions "webapp1" configured
$ kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
webapp1   4         4         4            2           5m

4つに増えている。ポッドも確認すると

$ kubectl get pods
NAME                       READY     STATUS    RESTARTS   AGE
webapp1-6c66d9cb4f-4tjfs   1/1       Running   0          54s
webapp1-6c66d9cb4f-89cb5   1/1       Running   0          54s
webapp1-6c66d9cb4f-9dlgw   1/1       Running   0          54s
webapp1-6c66d9cb4f-9l8t7   1/1       Running   0          6m

最初の1つが古く、新たに3つ増えている。

Deploy Guestbook Web App Example

This scenario explains how to launch a simple, multi-tier web application using Kubernetes and Docker. The Guestbook example application stores notes from guests in Redis via JavaScript API calls. Redis contains a master (for storage), and a replicated set of redis 'slaves'.

Step 1 - Start Kubernetes

クラスタを立ち上げてノードを確認する

master $ kubectl cluster-info
Kubernetes master is running at https://172.17.0.37:6443
KubeDNS is running at https://172.17.0.37:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
master $ kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
master    Ready     master    28m       v1.10.0
node01    Ready     <none>    28m       v1.10.0

Step 2 - Redis Master Controller

まずは Replication Controller をYAMLの設定ファイルから作成する。設定ファイルは以下:

apiVersion: v1
kind: ReplicationController
metadata:
  name: redis-master
  labels:
    name: redis-master
spec:
  replicas: 1
  selector:
    name: redis-master
  template:
    metadata:
      labels:
        name: redis-master
    spec:
      containers:
      - name: master
        image: redis:3.0.7-alpine
        ports:
        - containerPort: 6379

適用する

$ kubectl create -f redis-master-controller.yaml
replicationcontroller "redis-master" created

確認する

$ kubectl get rc
NAME           DESIRED   CURRENT   READY     AGE
redis-master   1         1         1         25s

$ kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
redis-master-zgbdj   1/1       Running   0          1m

Step 3 - Redis Master Service

サービスを起動させる。先と同様設定ファイルを適用させて状態を確認する。

apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels:
    name: redis-master
spec:
  ports:
    # the port that this service should serve on
  - port: 6379
    targetPort: 6379
  selector:
    name: redis-master

適用させる

$ kubectl create -f redis-master-service.yaml
service "redis-master" created

状態を確認する

$ kubectl get services
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP    35m
redis-master   ClusterIP   10.109.95.247   <none>        6379/TCP   21s

$ kubectl describe svc redis-master
Name:              redis-master
Namespace:         default
Labels:            name=redis-master
Annotations:       <none>
Selector:          name=redis-master
Type:              ClusterIP
IP:                10.109.95.247
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.40.0.2:6379
Session Affinity:  None
Events:            <none>

Step 4 - Replication Slave Pods

この例では、マスターからデータを複製するRedisスレーブを実行します。

apiVersion: v1
kind: ReplicationController
metadata:
  name: redis-slave
  labels:
    name: redis-slave
spec:
  replicas: 2
  selector:
    name: redis-slave
  template:
    metadata:
      labels:
        name: redis-slave
    spec:
      containers:
      - name: worker
        image: gcr.io/google_samples/gb-redisslave:v1
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access an environment variable to find the master
          # service's host, comment out the 'value: dns' line above, and
          # uncomment the line below.
          # value: env
        ports:
        - containerPort: 6379

適用させて、状態を確認する。

$ kubectl create -f redis-slave-controller.yaml
replicationcontroller "redis-slave" created

$ kubectl get rc
NAME           DESIRED   CURRENT   READY     AGE
redis-master   1         1         1         7m
redis-slave    2         2         2         17s

Step 5 - Redis Slave Service

apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  labels:
    name: redis-slave
spec:
  ports:
    # the port that this service should serve on
  - port: 6379
  selector:
    name: redis-slave
master $ kubectl create -f redis-slave-service.yaml
service "redis-slave" created
master $ kubectl get services
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP    40m
redis-master   ClusterIP   10.109.95.247    <none>        6379/TCP   5m
redis-slave    ClusterIP   10.102.120.172   <none>        6379/TCP   3s

Step 6 - Frontend Replicated Pods

Webアプリケーションのコンテナを立ち上げる。

apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
  labels:
    name: frontend
spec:
  replicas: 3
  selector:
    name: frontend
  template:
    metadata:
      labels:
        name: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access environment variables to find service host
          # info, comment out the 'value: dns' line above, and uncomment the
          # line below.
          # value: env
        ports:
        - containerPort: 80
master $ kubectl create -f frontend-controller.yaml
replicationcontroller "frontend" created
master $ kubectl get rc
NAME           DESIRED   CURRENT   READY     AGE
frontend       3         3         3         4s
redis-master   1         1         1         11m
redis-slave    2         2         2         3m
master $ kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
frontend-gb4ds       1/1       Running   0          7s
frontend-vz68p       1/1       Running   0          7s
frontend-wjc9z       1/1       Running   0          7s
redis-master-zgbdj   1/1       Running   0          11m
redis-slave-h72vr    1/1       Running   0          3m
redis-slave-jsgk9    1/1       Running   0          3m

Step 7 - Guestbook Frontend Service

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    name: frontend
spec:
  # if your cluster supports it, uncomment the following to automatically create
  # an external load-balanced IP for the frontend service.
  # type: LoadBalancer
  type: NodePort
  ports:
    # the port that this service should serve on
    - port: 80
      nodePort: 30080
  selector:
    name: frontend
master $ kubectl create -f frontend-service.yaml
service "frontend" created
master $ kubectl get services
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
frontend       NodePort    10.101.212.200   <none>        80:30080/TCP   2s
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP        43m
redis-master   ClusterIP   10.109.95.247    <none>        6379/TCP       8m
redis-slave    ClusterIP   10.102.120.172   <none>        6379/TCP       3m

Step 8 - Access Guestbook Frontend

30080番ポートにアクセスして閲覧できることを確認する

Networking Introduction

Step 1 - Cluster IP

クラスタIPは、Kubernetesサービスを作成する際のデフォルトの方法です。このサービスには、他のコンポーネントがポッドにアクセスするために使用できる内部IPが割り当てられています。

service "webapp1-clusterip-svc" created
deployment.extensions "webapp1-clusterip-deployment" created
master $ cat clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp1-clusterip-svc
  labels:
    app: webapp1-clusterip
spec:
  ports:
  - port: 80
  selector:
    app: webapp1-clusterip
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1-clusterip-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: webapp1-clusterip
    spec:
      containers:
      - name: webapp1-clusterip-pod
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80
---

Step 2 - Target Port

ターゲットポートは、アプリケーションがリッスンしているポートからサービスが利用可能なポートを切り離すことができます。TargetPortは、アプリケーションが待機するように設定されているポートです。ポートは、外部からアプリケーションにアクセスする方法です。

apiVersion: v1
kind: Service
metadata:
  name: webapp1-clusterip-targetport-svc
  labels:
    app: webapp1-clusterip-targetport
spec:
  ports:
  - port: 8080
    targetPort: 80
  selector:
    app: webapp1-clusterip-targetport
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1-clusterip-targetport-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: webapp1-clusterip-targetport
    spec:
      containers:
      - name: webapp1-clusterip-targetport-pod
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80

Step 3 - NodePort

TargetPortとClusterIPがクラスタ内で利用可能になっている間、NodePortは定義された静的ポートを介して各ノードのIP上でサービスを公開します。クラスタ内のどのノードにアクセスしても、定義されたポート番号に基づいてサービスにアクセスできます。

apiVersion: v1
kind: Service
metadata:
  name: webapp1-nodeport-svc
  labels:
    app: webapp1-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30080
  selector:
    app: webapp1-nodeport
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1-nodeport-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: webapp1-nodeport
    spec:
      containers:
      - name: webapp1-nodeport-pod
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80

Step 4 - External IPs

apiVersion: v1
kind: Service
metadata:
  name: webapp1-externalip-svc
  labels:
    app: webapp1-externalip
spec:
  ports:
  - port: 80
  externalIPs:
  - 172.17.0.14
  selector:
    app: webapp1-externalip
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1-externalip-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: webapp1-externalip
    spec:
      containers:
      - name: webapp1-externalip-pod
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80

Step 5 - Load Balancer

EC2やAzureなどのクラウドで実行する場合、クラウドプロバイダ経由で発行されたパブリックIPアドレスを設定して割り当てることができます。

apiVersion: v1
kind: Service
metadata:
  name: webapp1-loadbalancer-svc
  labels:
    app: webapp1-loadbalancer
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: webapp1-loadbalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1-loadbalancer-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: webapp1-loadbalancer
    spec:
      containers:
      - name: webapp1-loadbalancer-pod
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80

Running Stateful Services on Kubernetes

Step 1 - Deploy NFS Server

NFSは、ノードがネットワーク上でデータを読み書きできるようにするプロトコルです。このプロトコルは、マスターノードにNFSデーモンを実行させ、データを格納することによって機能します。このマスターノードは、特定のディレクトリをネットワーク上で使用可能にします。

クライアントは、ドライブマウントによって共有されたマスターにアクセスします。アプリケーションの観点からは、ローカルディスクに書き込んでいます。カバーの下では、NFSプロトコルはそれをマスターに書き込みます。

$ docker run -d --net=host --privileged --name nfs-server katacoda/contained-nfs-server:centos7 /exports/data-0001 /exports/data-0002

NFSサーバーは、data-0001とdata-0002の2つのディレクトリを公開します。次のステップでは、これを使用してデータを格納します。


Step 2 - Deploy Persistent Volume

Kubernetesが利用可能なNFS共有を理解するためには、PersistentVolume設定が必要です。PersistentVolumeは、AWS EBSボリューム、GCEストレージ、OpenStack Cinder、Glusterfs、NFSなど、データを格納するためのさまざまなプロトコルをサポートしています。設定は、ストレージとAPI間の抽象化を提供し、一貫した経験を可能にします。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: <friendly-name>
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    server: <server-name>
    path: <shared-path>

Step 3 - Deploy Persistent Volume Claim

永続ボリュームが利用可能になると、アプリケーションはそのボリュームを要求することができます。この主張は、アプリケーションが誤って同じボリュームに書き込んだり、競合やデータの破損を引き起こしたりするのを防ぐように設計されています。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim-mysql
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

Step 4 - Use Volume

Podでも指定できる

apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    name: mysql
spec:
  containers:
  - name: mysql
    image: openshift/mysql-55-centos7
    env:
      - name: MYSQL_ROOT_PASSWORD
        value: yourpassword
      - name: MYSQL_USER
        value: wp_user
      - name: MYSQL_PASSWORD
        value: wp_pass
      - name: MYSQL_DATABASE
        value: wp_db
    ports:
      - containerPort: 3306
        name: mysql
    volumeMounts:
      - name: mysql-persistent-storage
        mountPath: /var/lib/mysql/data
  volumes:
    - name: mysql-persistent-storage
      persistentVolumeClaim:
        claimName: claim-mysql
---
apiVersion: v1
kind: Pod
metadata:
  name: www
  labels:
    name: www
spec:
  containers:
  - name: www
    image: nginx:alpine
    ports:
      - containerPort: 80
        name: www
    volumeMounts:
      - name: www-persistent-storage
        mountPath: /usr/share/nginx/html
  volumes:
    - name: www-persistent-storage
      persistentVolumeClaim:
        claimName: claim-http

Step 5 - Read/Write Data


Liveness and Readiness Healthchecks

Step 1 - Launch Cluster

launch.sh を実行してクラスタを起動し、 deploy.yaml を適用する。

kind: List
apiVersion: v1
items:
- kind: ReplicationController
  apiVersion: v1
  metadata:
    name: frontend
    labels:
      name: frontend
  spec:
    replicas: 1
    selector:
      name: frontend
    template:
      metadata:
        labels:
          name: frontend
      spec:
        containers:
        - name: frontend
          image: katacoda/docker-http-server:health
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 1
            timeoutSeconds: 1
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 1
            timeoutSeconds: 1
- kind: ReplicationController
  apiVersion: v1
  metadata:
    name: bad-frontend
    labels:
      name: bad-frontend
  spec:
    replicas: 1
    selector:
      name: bad-frontend
    template:
      metadata:
        labels:
          name: bad-frontend
      spec:
        containers:
        - name: bad-frontend
          image: katacoda/docker-http-server:unhealthy
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 1
            timeoutSeconds: 1
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 1
            timeoutSeconds: 1
- kind: Service
  apiVersion: v1
  metadata:
    labels:
      app: frontend
      kubernetes.io/cluster-service: "true"
    name: frontend
  spec:
    type: NodePort
    ports:
    - port: 80
      nodePort: 30080
    selector:
      app: frontend

Step 2 - Readiness Probe

$ kubectl get pods --selector="name=bad-frontend"
NAME                 READY     STATUS    RESTARTS   AGE
bad-frontend-psbm8   0/1       Running   2          51s

Step 3 - Liveness Probe

Use Kubernetes To Manage Secrets And Passwords

Step 1 - Start Kubernetes

Step 2 - Create Secrets

Kubernetesは、シークレットをBase64文字列としてエンコードする必要があります。コマンドラインツールを使用して、Base64文字列を作成し、変数として格納してファイルに使用することができます。

$ username=$(echo -n "admin" | base64)
$ password=$(echo -n "a62fjbd37942dcs" | base64)
$ echo $username
YWRtaW4=
$ echo $password
YTYyZmpiZDM3OTQyZGNz

マニフェストファイルは次のようになる

apiVersion: v1
kind: Secret
metadata:
  name: test-secret
type: Opaque
data:
  username: YWRtaW4=
  password: YTYyZmpiZDM3OTQyZGNz

適用する。

$ kubectl create -f secret.yaml
secret "test-secret" created

確認する。

$ kubectl get secrets
NAME                  TYPE                                  DATA      AGE
default-token-jbdhc   kubernetes.io/service-account-token   3         6m
test-secret           Opaque                                2         20s

Step 3 - Consume via Environment Variables

環境変数として利用する場合は、secretKeyRefを使う。

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
    - name: mycontainer
      image: alpine:latest
      command: ["sleep", "9999"]
      env:
        - name: SECRET_USERNAME
          valueFrom:
            secretKeyRef:
              name: test-secret
              key: username
        - name: SECRET_PASSWORD
          valueFrom:
            secretKeyRef:
              name: test-secret
              key: password
  restartPolicy: Never

適用して確認する。

master $ kubectl create -f secret-env.yaml
pod "secret-env-pod" created
master $ kubectl exec -it secret-env-pod env | grep SECRET_
SECRET_USERNAME=admin
SECRET_PASSWORD=a62fjbd37942dcs

Step 4 - Consume via Volumes

base64だとリポジトリに含めることができないので、次のようにパスを指定する

apiVersion: v1
kind: Pod
metadata:
  name: secret-vol-pod
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: test-secret
  containers:
    - name: test-container
      image: alpine:latest
      command: ["sleep", "9999"]
      volumeMounts:
          - name: secret-volume
            mountPath: /etc/secret-volume

Create Ingress Routing

Kubernetes have advanced networking capabilities that allow Pods and Services to communicate inside the cluster's network. An Ingress enables inbound connections to the cluster, allowing external traffic to reach the correct Pod.

Ingress enables externally-reachable urls, load balance traffic, terminate SSL, offer name based virtual hosting for a Kubernetes cluster.

In this scenario you will learn how to deploy and configure Ingress rules to manage incoming HTTP requests.

Step 1 - Create Deployment

以下の deployment.yaml を適用し、Deploymentを作る。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: webapp1
    spec:
      containers:
      - name: webapp1
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: webapp2
    spec:
      containers:
      - name: webapp2
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: webapp3
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: webapp3
    spec:
      containers:
      - name: webapp3
        image: katacoda/docker-http-server:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: webapp1-svc
  labels:
    app: webapp1
spec:
  ports:
  - port: 80
  selector:
    app: webapp1
---
apiVersion: v1
kind: Service
metadata:
  name: webapp2-svc
  labels:
    app: webapp2
spec:
  ports:
  - port: 80
  selector:
    app: webapp2
---
apiVersion: v1
kind: Service
metadata:
  name: webapp3-svc
  labels:
    app: webapp3
spec:
  ports:
  - port: 80
  selector:
    app: webapp3

確認すると、作成されていることがわかる

$ kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
webapp1   1         1         1            0           4s
webapp2   1         1         1            0           4s
webapp3   1         1         1            0           4s

Step 2 - Deploy Ingress

Ingressはレプリケーションコントローラとして展開されます。このコントローラーは、NginxやHAProxyなどのソフトウェア・ロード・バランサーとKubernetesの統合を組み合わせて、定義されたルールに基づいて自身を構成します。

以下のYAMLファイルでは、nginxベースのIngressコントローラと、ExternalIPを使用する外部接続に対してポート80で使用可能にするサービスを定義しています。Kubernetesクラスターがクラウドプロバイダーで実行されていた場合は、LoadBalancerサービスタイプを使用します。

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-ingress-rc
  labels:
    app: nginx-ingress
spec:
  replicas: 1
  selector:
    app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
    spec:
      containers:
      - image: nginxdemos/nginx-ingress:0.9.0
        name: nginx-ingress
        ports:
        - containerPort: 80
          hostPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-lb
  labels:
    app: nginx-ingress
spec:
  externalIPs:
  - 172.17.0.35
  ports:
  - port: 80
    name: http
    targetPort: 80
  selector:
    app: nginx-ingress

Step 3 - Deploy Ingress Rules

ingress-rule.yaml ルールは、要求ホスト(ドメイン)、または要求のパス、またはその両方の組み合わせに基づいています。以下をみると、パスによってエンドポイントが分かれている。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: webapp-ingress
spec:
  rules:
  - host: my.kubernetes.example
    http:
      paths:
      - path: /webapp1
        backend:
          serviceName: webapp1-svc
          servicePort: 80
      - path: /webapp2
        backend:
          serviceName: webapp2-svc
          servicePort: 80
      - backend:
          serviceName: webapp3-svc
          servicePort: 80

作成します。

$ kubectl create -f ingress-rules.yaml
ingress.extensions "webapp-ingress" created

確認します。

$ kubectl get ing
NAME             HOSTS                   ADDRESS   PORTS     AGE
webapp-ingress   my.kubernetes.example             80        32s

Helm Package Manager

Install Helm

$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.8.2-linux-amd64.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 14.2M  100 14.2M    0     0  12.5M      0  0:00:01  0:00:01 --:--:-- 12.5M
$ tar -xvf helm-v2.8.2-linux-amd64.tar.gz
linux-amd64/
linux-amd64/helm
linux-amd64/README.md
linux-amd64/LICENSE
$ mv linux-amd64/helm /usr/local/bin/

$ helm init
Creating /root/.helm
Creating /root/.helm/repository
Creating /root/.helm/repository/cache
Creating /root/.helm/repository/local
Creating /root/.helm/plugins
Creating /root/.helm/starters
Creating /root/.helm/cache/archive
Creating /root/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈

Search For Chart

helmは検索して、inspectすれば設定ファイルの雛形が手に入る。

$ helm search redis
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION
stable/prometheus-redis-exporter        0.3.0           0.16.0          Prometheus exporter for Redis metrics
stable/redis                            3.7.2           4.0.10          Open source, advanced key-value store. Itis of...
stable/redis-ha                         2.2.1           4.0.8-r0        Highly available Redis cluster with multiple se...
stable/sensu                            0.2.3           0.28            Sensu monitoring framework backed by the Redis ...

Deploy Redis

設定を適用する場合は、 help install stable/redis でよい。インストール一覧を確認するときは helm ls を実行する。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment