IT・ビッグデータ徒然ブログ

関西でインフラ、データ基盤系のエンジニアになりたい

Kubernetesを勉強しつつ、用語を整理してみる

kubernetes.io

最近Kubernetesに興味をもっていろいろいじっている。

随時更新予定。

Kubernetesとは、、、

  • 仮想化の一種であるコンテナ技術のオーケストラレーションができるツール
  • Googleが開発して現在はOSS化している

他のDockerにもオーケストラレーション機能はあることはあるが、 Kubernetesの特徴としては、

  • 複数のノード(サーバ)を1つのコンテナサーバとしてみなすことができる
  • スケールアウトが容易(ノード追加)
  • サービスのローリングアップデートが可能
  • アップデートしても、前のバージョンのコンテナが残っている(イミュータブル)なので、戻すことも容易
  • 宣言的設定→望ましい状態に満たないときはKubernetesがうまいことやってくれる

とかですかね。

(このあたりはGoogleらしいというか、分散システム(YARNとかMesosとか)の感じを受けました)

kubectlインストール

brew install kubernetes-cli

minikubeインストール

curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.28.2/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

他のインストール方法はこちら

Install Minikube - Kubernetes

github.com

YAML

Kubernetesでコンテナ起動等なんらかの定義をする際はYAMLで記述する

起動

定義を実行するときは、 kubectl apply -f <YAML定義>で実行する。 それかkubectl runでもできる

Kubernetesの情報確認

kubectl get <項目>で見れる

# Pod情報
kubectl get pods

# Deployment情報
kubectl get deployments

# Replicaset
kubectl get rs

詳細情報の取得

kubectl describe <項目> <名前>

#特定の定義情報を取得
kubectl describe pod 

Pod

  • コンテナの塊
  • Kubernetesで操作できる最小単位
  • 基本的には1Podにつき1コンテナ
  • 複数のコンテナが常に同期していないといけない場合は1Podにくるめる
    • 入門Kubernetesによると「このコンテナはそれぞれ違うマシンに配置されても正常に動作するかどうか」がNoなら1つのPodにまとめるのがいいとのこと
      • できるだけ疎結合であることを推奨 -> マイクロサービス化

Podを定義するときには、コンテナのポートPodのポートフォワーディングを設定する。

Label

  • Podや後述するDeploymentやServiceなどにつけられるタグのようなもの
  • Key/Value形式で設定
  • app:tomcatというラベルがついているPodをすべて落とすみたいなラベル単位での操作が可能になる
apiVersion: v1
kind: Pod
metadata:
   name: tomcat-pod
   labels:
      app: tomcat
  spec:
      containers:
      - name: tomcat
         image: tomcat:8.0
         ports:
         - name: tomcat-port
            containerPort: 8080
  • tomcat-podという名前のPodを作成
  • app -> tomcatというラベルを作成
  • コンテナの名前はtomcat、使用するコンテナイメージはtomcat:8.0
  • Podの8080がコンテナポートの8080にフォワーディング

kubectl apply -f <コンテナイメージのyaml>クラスタにデプロイ

コンテナの起動を確認する場合は、

kubectl port-forward nodehelloworld.example.com <ローカルポート>:<Pod内のコンテナポート> でポートフォワーディングするとlocalhost:<ローカルポート>でアクセスできる

livenessProbeとreadinessProbe

要はコンテナ生きてる?という確認を行うもの。(Hadoopでいうハートビートみたいなやつ)

LivenessとReadinessの違いは

Liveness -> コンテナが起動しているか Readiness -> コンテナが応答するか

apiVersion: v1
kind: Pod
metadata:
   name: tomcat-pod
   labels:
      app: tomcat
spec:
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat:8.0
        ports:
        - containerPort : 8080
        livenessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 30
          timeoutSeconds: 10
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 3
          timeoutSeconds: 10
          failureThreshold: 3
  • livenessProbe
    • 8080ポートにアクセスして起動確認
    • コンテナ開始を30秒待つ
    • 30秒ごとに監視する
    • タイムアウトは10秒
    • 3回連続タイムアウトでコンテナが起動していないと解釈(Deploymentとかと組み合わせると自動で別のコンテナが起動したり)
  • ReadinessProbe
    • 8080ポートにアクセスして起動確認
    • コンテナ開始を15秒待つ
    • 3秒ごとに監視する
    • タイムアウトは10秒
    • 3回連続タイムアウトでコンテナが応答していないと解釈

Resource(requestとlimit)

コンテナに対して最低限要求するリソースと逆にこれ以上リソースをとるなというリミットを宣言できる

# 一部抜粋
spec:
      containers:
        - name: tomcat
        image: tomcat:9.0
        resources:
          requests:
            cpu: "500m" 
            memory: "128Mi"
          limits:
            cpu: "1000m"
            memory: "256Mi"
ports:
- containerPort: 8080
  • cpu
    • Min0.5コア、Max1コア
  • メモリ
    • Min128MB、Max256MB

Volume

Podが停止しても永続的に残るストレージのようなものを作成できる。

Volumeの定義はコンテナの定義を作る感覚で定義できる
(というよりストレージ用のコンテナを作る感覚に似ていると思う)

spec: 
  volumes:
    - name: "kuard-data" 
    nfs:
      server: my.nfs.server.local
      path: "/exports" 
containers:
#以下にコンテナの定義を書いたり

でコンテナにVolumeをマウントするときは、

spec:
      containers:
        - name: tomcat
        image: tomcat:9.0
        resources:
          requests:
            cpu: "500m" 
            memory: "128Mi"
          limits:
            cpu: "1000m"
            memory: "256Mi"
        volumeMounts:
          - mountPath: "/data" 
            name: "kuard-data"
ports:
- containerPort: 8080
  • volumeMounts内で指定したnameのVolumeを/dataにマウント

ReplicasetとDeamonset

Podを複数立てます。

  • 冗長化→負荷分散してくれる
  • 耐障害性→1つPodが落ちても大丈夫

ReplicasetとDaemonsetの違いは、

Replicaset

  • クラスタ全体内で決められた数のPodを生成
    • 実際のノードのどこに配置するかは自由
  • 定義を記述するときに、合わせてPod(コンテナ)の定義もできる
apiVersion: apps/v1beta2
kind: Replicaset
metadata:
  name: tomcat
spec:
  selector:
    matchLabels:
      app: tomcat
  replicas: 4
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat:9.0
        ports:
        - containerPort : 8080
  • Tomcatのコンテナが入っているPodを動かす
  • PodのIP:8080でこのコンテナにアクセスできる
  • PodはKubernetesクラスタ上に4つ複製される

これを実行した後、kubectl get rsを動かすと

$ kubectl get rs                  
NAME                           DESIRED   CURRENT   READY     AGE
tomcat-84bc588dcd   4         4         0         11s

こんな感じで結果が返ってくる。

Daemonset

  • クラスタ内のすべてのノードに対して1つ以上Podを生成
    • すべてのノードに対して監視用アプリケーションやログコレクタ(Fluentd等)のPodを配置したりできる

Service

外部から特定のPodにアクセスするための機能 ※本来はPod生成時に外部からアクセスできるIPが生成されるが、毎回調べるのが面倒なので、そこをServiceがうまい具合にやってくれる。

クラスタ内部はもちろん(TargetPort)、クラスタ外からのネットワークからのアクセスも可能(NodePort)

Deployment

  • Pod(のReplicaを含む)をアップデートできる
  • ローリングアップデート可能
  • Deploymentの定義実行時にReplicasetならびにPodの定義も記述できる

Job

  • なんらかの処理やワークフローを実行したいときに一時的に立ち上がるPodの定義

  • なんとなく、サーバレスっぽいなと直感で思ったけど違ってたら教えて。

  • 並列実行ができる

ConfigMap

Secrets

  • 見られたらまずい値を補完する機能
  • MySQLのパスワードとか、ApacheにわたすSSLの鍵とか