このブログを検索

この記事の内容は、個人の見解、検証の範囲のものであり、誤りがある可能性があります。
個人の責任において情報活用をお願いします。


ラベル SNT の投稿を表示しています。 すべての投稿を表示
ラベル SNT の投稿を表示しています。 すべての投稿を表示

2023年3月31日金曜日

やってみよう自動化ツール Ansible その6 動的PVCが使えるようにnfs-clientを自動で展開してみよう

今回は、Podに永久ストレージを自動で追加してくれる動的PVCを使えるように、nfs-clientの導入をやっていきます。
事前準備として、コントロールプレーンノード、ワーカーノードからNFSの領域がアクセスできるようにしておいてください。

NFS用意してないよっていう人は、以下の作業で検証用のNFSを適当に作ってください。
1. マウントする領域を作成する(mkdir /share/nfs)
2. yum install nfs-utils で nfs-utils をインストール
3. vi /etc/exports で通信設定を行う
/share/nfs NFSサーバーにアクセス可能にするネットワーク(rw,no_root_squash,async) 4. firewallを無効
5. サービスを起動する
systemctl start rpcbind systemctl start nfs
NFSを用意したら忘れずにWorkerノードにマウントしてください
1. マウントポイント作成(mkdir /share/nfs-client)
2. yum install nfs-utils で nfs-utils をインストール
3. mount -v -t nfs NFSのIPアドレス:/share/nfs /share/nfs-client
準備ができたら、次に進みましょう。
まず、手動でやる際のnfs-client導入手順確認です
1. nfs-clientをインストールするためにhelmを利用するので導入します

   curl -O https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
   bash ./get-helm-3

2. helmからnfs-clientをデプロイできるようにリポジトリを追加します

   helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

3. helmからnfs-clientをデプロイします

   helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
     --set nfs.server=NFSのIPアドレス \
     --set nfs.path=/share/nfs
手順としては上記で完了です。
これをもとにansible用のプレイブックを作成していきましょう。

まず、今回もrolesを使っていこうと思うので、roles/nfs_client/tasks/main.yaml を作成し以下の内容を記載します。
---
- name: helm get
  shell: curl -O https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3

- name: helm install
  shell: bash ./get-helm-3

- name: helm add repo
  shell: helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

- name: nfs-client deploy
  shell: helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=NFSのIPアドレス --set nfs.path=/share/nfs
---
続いて前回作成したrolesを呼び出す用のプレイブック(k8s-add.yaml)に、このrolesを追加します。
- name: setup k8s
  hosts: kubectl
  remote_user: root

  tasks:
#    - name: metallb setup
#      include_role:
#        name: MetalLB

    - name: nfs-client setup
      include_role:
        name: nfs_client
前回作成済みのMetalLBがすでにあるので、MetalLBについての処理はコメントアウトしています。
あとは、ansibleからプレイブックを実行するだけです。

ansible-playbook k8s-add.yaml
正常に処理が行われたら、PVCが使えるか確認してみましょう。
まず、以下のコマンドで nfs-client を導入したことにより追加された storage class と pod を確認します。
kubectl get pod,sc
nfs-subdir-external-provisioner-xxxxx という pod と nfs-client というstorage class ができていると思います。
現時点では pvc も pv もないことを確認しておいてください。
kubectl get pv,pvc
No resources found
では、pvcを作成するyamlを作成します。
pvc.yaml
----
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-provisioner
  annotations:
    volume.beta.kubernetes.io/storage-class: nfs-client
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
----
以下のコマンドでPVCを作成します。
kubectl apply -f pvc.yaml
pvc とそれに Bound された pv が作成されていることを確認してください。
# kubectl get pv,pvc
今回は以上となります。

2023年2月28日火曜日

やってみよう自動化ツール Ansible その5 タイプLBのSVCを使えるようにMetalLBを自動で展開してみよう

えー、残念ながらコントロールプレーンへワーカーの追加を自動で行うのはうまくいきませんでした。
できないときはすっぱりあきらめて次に進みましょう。
というわけで今回は、お手製k8sでは使えないLBの役割を満たしてくれるMetalLBの構築をやっていきましょう。

その前に、前回のままだとコントロールプレーンで以下のコマンドを実施し、接続用の情報を出力しましょう。
kubeadm token create --print-join-command
このコマンドの出力をワーカーで実行してクラスターへ追加します。

コントロールプレーンへワーカー追加後は、以下のコマンドでCNI(今回はflannnel)を追加しましょう。
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

ではMetalLBの作業を自動化するにあたってMetalLBのインストール作業を確認します。
作業する端末はansibleを実行するサーバに変更してください。

公式
https://metallb.universe.tf/installation/

手順的には、以下のコマンドでインストール
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-frr.yaml

IPアドレスのレンジ等を決めるには、以下のような構成ファイルをyamlで作成してこちらも apply する。
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2advertisement
  namespace: metallb-system
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ipaddresspool
  namespace: metallb-system
spec:
  addresses:
  - xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx ★環境に合わせてレンジを設定してください。
手順的にはこれだけなのでひとまとめにしてしまいたいですが、k8sを作ってはMetaLBを設定するという作業はあり得るのでこちらもrolesで呼び出せるようにしておきましょう。
※新環境を作る際にはIPアドレスのレンジを変更しておくことを忘れないでください。

と、いうわけなんですが、kubectlを実行するのはansibleを実行する端末ではありません。
コマンド自体は ansible を実行する際に shell を利用してコマンドを実行すればいいのですが、構成ファイルの方はコントロールプレーンへ送る必要があります。
kubectl を ansible実行端末で使えるようにするという手もありますが、今回のシリーズは ansible を使っていくことを目的としているのでなるべく ansible で頑張ろうと思います。

というわけで、手順的には以下の順になります。
構成ファイルは MetalLB_conf.yaml として作成し、ansible 実行時のカレントディレクトリに作成します。

1. ファイルをコントロールプレーンへ送る
2. 構成ファイルを apply する
3. MetalLB を apply する

roles/MetalLB/tasks/main.yaml への記述内容としては以下になります。
- name: Config File Copy
  copy:
    src: MetalLB_conf.yaml
    dest: /root/MetalLB_conf.yaml

- name: Config apply
  shell : kubectl apply -f /root/MetalLB_conf.yaml

- name: MetalLB apply
  shell : kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-frr.yaml

そしてこれを呼び出す k8s-add.yaml を以下のように作成します。

- name: k8s add
  hosts: kubectl
  remote_user: root

  tasks:
    - name: setup
      include_role:
        name: MetalLB
今回は単品となりますが、この yaml に今回のように必要に応じて追加する機能への処理を足していくことで、k8s 構築後の作業が楽になるはずです。
準備ができたら以下のコマンドで処理を実行してみましょう。

ansible-playbook k8s-add.yaml

エラーにならなければ問題なく成功していると思いますが、確認したい場合はLBタイプのServiceを適当に作成して『EXTERNAL-IP』からLBに与えた範囲からIPアドレスが払い出されているか確認してください。
次は nfs-client の構築を自動化したいと思います。

2023年1月13日金曜日

やってみよう自動化ツール Ansible その4 ワーカーノード作成を自動でつくってみる

あけましておめでとうございます。
今年も当ブログをよろしくお願いします。

今回は去年作ったコントロールプレーンに追加するワーカーノードを作成していこうと思います。
なお、今回は1つの yamlファイルに命令をすべて書くのではなく、処理を『OSのセットアップ』『Containerd のセットアップ』『ワーカー用セットアップ』3つに分けて呼び出したいと思います。
ansible-playbook コマンドで呼び出すファイルには『コレとコレとコレの処理を使います』と書く感じですね。

実際にはこんな感じになります。
worker_node.yaml
- name: setup worker node
  hosts: worker
  remote_user: root

  tasks:
    - name: setup os
      include_role:
        name: os-set

    - name: setup containerd
      include_role:
        name: containerd-set

    - name: setup worker
      include_role:
        name: worker-set

このように記述すると、rolesディレクトリ配下のディレクトリ『os-set』『containerd-set』『worker-set』にある『tasks』ディレクトリ内の『main.yaml』に書かれた処理を読み込んでくれます。
文章だとよくわからないので以下のような構造にする必要があるということになります。
├── worker_node.yaml
│ 
├── roles
│     ├── os-set
│     │     └── tasks
│     │            └── main.yaml
│     │ 
│     ├── containerd-set
│     │     └── tasks
│     │            └── main.yaml
│     │ 
│     └── worker-set
│            └── tasks
│                   └── main.yaml
では、それぞれの処理を見ていきましょう。
まずはOSのセットアップです。
SElinux停止やFWの停止をしています。
roles/os-set/tasks/main.yaml
  - name: SElinux Disable
    ansible.posix.selinux: state=disabled
    become: true

  - name: Reboot
    ansible.builtin.reboot: reboot_timeout=600
    become: true

  - name: FW Stop
    service:
      name: firewalld
      state: stopped
      enabled: no
続いて、Containerd をインストールします。
  - name: Swap Stop swapoff
    shell : swapoff -a

  - name: Swap Stop /etc/fstab
    shell : sed -i '/centos-swap/s/^/# /g' /etc/fstab

  - name: kernel module file create
    file:
      path: /etc/modules-load.d/containerd.conf
      state: touch

  - name: kernel module file add line
    lineinfile:
      dest: /etc/modules-load.d/containerd.conf
      line: "{{ item }}"
    with_items:
      - "overlay"
      - "br_netfilter"

  - name: kernel module Load
    shell : modprobe overlay
    shell : modprobe br_netfilter

  - name: kernel parameter file create
    file:
      path: /etc/sysctl.d/99-kubernetes-cri.conf
      state: touch

  - name: kernel parameter file add line
    lineinfile:
      dest: /etc/sysctl.d/99-kubernetes-cri.conf
      line: "{{ item }}"
    with_items:
      - "net.bridge.bridge-nf-call-iptables  = 1"
      - "net.ipv4.ip_forward                 = 1"
      - "net.bridge.bridge-nf-call-ip6tables = 1"

  - name: System Reload
    shell : sysctl --system

  - name: Package Install
    yum:
      name: yum-utils
      name: device-mapper-persistent-data
      name: lvm2

  - name: containerd add repository
    shell : yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

  - name: Containerd Install
    yum:
      name: containerd.io

  - name: containerd Setting folder create
    file:
      path: "/etc/containerd"
      state: directory

  - name: containerd Setting file create
    shell : containerd config default | sudo tee /etc/containerd/config.toml

  - name: containerd Restart
    service:
      name: containerd
      state: restarted
      enabled: no
最後に、kubeadmin をインストールします。
roles/worker-set/tasks/main.yaml
  - name: kubernetes.repo create
    file:
      path: /etc/yum.repos.d/kubernetes.repo
      state: touch

  - name: add kubernetes.repo
    lineinfile:
      dest: /etc/yum.repos.d/kubernetes.repo
      line: "{{ item }}"
    with_items:
      - "[kubernetes]"
      - "name=Kubernetes"
      - "baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64"
      - "enabled=1"
      - "gpgcheck=1"
      - "repo_gpgcheck=1"
      - "gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg"

  - name: Install kubeadm
    yum:
      name: kubeadm
上記のファイルを正しく配置して準備はおしまいです。
あとは、ansible-playbook worker_node.yaml を実行すると自動で処理を行ってくれるはずです。

このあと、コントロールプレーンで kubeadm token create --print-join-command を実行し、ワーカーで kubeadm join を実行するのですがそこはちょっと手動でお願いします・・・ 実はそこまで試したんですが、token を表示させて register: するところまではうまくいったんですがそこからコマンドだけを引っ張り出すのがうまくいかなかったのでいったん保留としています。
うまくいったら次回はそこの自動化について書きたいと思います。

2022年12月23日金曜日

やってみよう自動化ツール Ansible その3 k8sのコントロールプレーンを自動化してみる

今回は、前回準備を整えた環境にAnsibleをつかってKubernetesを自動インストールしていこうと思います。
実行する内容としては、Kubernetesをインストールする際に使うkubeadmのyumリポジトリを追加、kubeadmのインストール、kubeadm int でコントロールプレーンの作成、kubectlコマンド実行のためのkubeconfig用設定となります。

用意するプレイブックは以下の内容となります。
- name: setup Containerd
  hosts: kubernetes
  remote_user: root

  tasks:
  - name: kubernetes.repo create
    file:
      path: /etc/yum.repos.d/kubernetes.repo
      state: touch

  - name: add kubernetes.repo
    lineinfile:
      dest: /etc/yum.repos.d/kubernetes.repo
      line: "{{ item }}"
    with_items:
      - "[kubernetes]"
      - "name=Kubernetes"
      - "baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64"
      - "enabled=1"
      - "gpgcheck=1"
      - "repo_gpgcheck=1"
      - "gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg"

  - name: Install kubeadm
    yum:
      name: kubeadm

  - name: Kubernetes Setup
    shell : kubeadm init --apiserver-advertise-address=172.20.73.91 --pod-network-cidr=10.244.0.0/16

  - name: $HOME/.kube create
    shell : mkdir -p $HOME/.kube

  - name: copy admin.conf
    shell : sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

  - name: chown $HOME/.kube/config
    shell : sudo chown $(id -u):$(id -g) $HOME/.kube/config

task: 以降について解説します。
『kubernetes.repo create』これは、次のタスクで内容を記述していくためのファイル作成部分になります。
『add kubernetes.repo』これは、yum で kubeadm をインストールする際に必要なリポジトリの内容を追加しています。
『Install kubeadm』これは、yum で kubeadm をインストールしています。
『Kubernetes Setup』これは、kubeadm を使用して Kubernetes を構築しています。CNI は flannel を使用しています。
『$HOME/.kube create』『copy admin.conf』『chown $HOME/.kube/config』この3つは、Kubernetes へ対して操作を行う kubectl を使うための処理となっています。
kubectl は $HOME/.kube/config に書いてある接続に必要な情報を読み取って Kubernetes とやり取りをするため、ディレクトリを作って情報が記入されているファイルをコピーして権限を整えているという処理になります。

Kubernetes をよくご存じの方は --pod-network-cidr から flannel って… と思われる方もいるかもしれませんが、私が初めて Kubernetes を構築して Pod の通信についてあれやこれやと頭を悩ませ、VXLAN やカプセル化といった仕組みを理解するまで一緒に付き合ってくれた思い入れのある機能なので使いたくなってちゃうんですよねw
どうかご容赦ください。

この後は、コントロールプレーンに追加する用のワーカーの作成になります。
こちらについては、今まで作成した OS の設定、Containerd の構築、Kubernetes の構築、これらの処理を roles を利用して呼び出す形で作成したいともいます。

今年もブログを読んでいただきありがとうございました。
来年もよろしくお願いします。

よいおとしを~

2022年11月30日水曜日

やってみよう自動化ツール Ansible その2

今回は、実際に Ansible のプレイブックを作成して自動でいろいろファイルに書き込んだり、パッケージのインストールやサービスの設定をやってみましょう。
具体的には、Docker と同じくコンテナの管理ができる Containerd のインストールを行うための各設定をおこない、インストールしてサービスの起動を行ってみます。

私が以前書いた記事を読んだことがある方は、せっかく前いろいろやったのに Docker 使わないの? と思われるかもしれません。
ちょっとした理由がありまして・・・

この環境を使って次回以降に Kubernetes(以降 k8s) を作成していこうと思ったのですが、k8s が Docker で構築できなくなりました。
K8s は Docker からコンテナを管理する部分の機能を使わせてもらいたくて Dockershim というモジュールを用意していたのですが、k8s がそれを使うのをやめることにしたためです。
昔は Docker しかなかったんですが、現在は Docker と同様にコンテナを管理する機能を提供してくれるCRIランタイム(Containerd 等)があります。
そちらを使ったほうが無駄が省けるという事のようです。(開発する部品が少なくなるほうが開発側も楽でしょうしね)

それでは、実際にどんなプレイブックを用意するのかこちらをご覧ください。
これは、ザーッっと流してみてください。
のちほど分解して説明します。(もしかしたら、コマンドとかからなんとなく処理がわかるかもしれませんが・・・)

Containerd のための設定の他に、k8s 用の設定変更も一部入っています。
参考情報:
https://kubernetes.io/ja/docs/setup/production-environment/container-runtimes/#containerd
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

ファイル名:containerd-set.yaml
- name: setup Containerd
  hosts: continard
  remote_user: root

  tasks:
  - name: Swap Stop
    shell : swapoff -a
    shell : sed -i '/centos-swap/s/^/# /g' /etc/fstab

  - name: SElinux Disable
    ansible.posix.selinux: state=disabled
    become: true

  - name: Reboot
    ansible.builtin.reboot: reboot_timeout=600
    become: true

  - name: FW Stop
    service:
      name: firewalld
      state: stopped
      enabled: no

  - name: kernel module file create
    file:
      path: /etc/modules-load.d/containerd.conf
      state: touch

  - name: kernel module file add line
    lineinfile:
      dest: /etc/modules-load.d/containerd.conf
      line: "{{ item }}"
    with_items:
      - "overlay"
      - "br_netfilter"

  - name: kernel module Load
    shell : modprobe overlay
    shell : modprobe br_netfilter

  - name: kernel parameter file create
    file:
      path: /etc/sysctl.d/99-kubernetes-cri.conf
      state: touch

  - name: kernel parameter file add line
    lineinfile:
      dest: /etc/sysctl.d/99-kubernetes-cri.conf
      line: "{{ item }}"
    with_items:
      - "net.bridge.bridge-nf-call-iptables  = 1"
      - "net.ipv4.ip_forward                 = 1"
      - "net.bridge.bridge-nf-call-ip6tables = 1"

  - name: System Reload
    shell : sysctl --system

  - name: Package Install
    yum:
      name: yum-utils
      name: device-mapper-persistent-data
      name: lvm2

  - name: containerd add repository
    shell : yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

  - name: Containerd Install
    yum:
      name: containerd.io

  - name: containerd Setting folder create
    file:
      path: "/etc/containerd"
      state: directory

  - name: containerd Setting file create
    shell : containerd config default | sudo tee /etc/containerd/config.toml

  - name: containerd Restart
    service:
      name: containerd
      state: restarted
      enabled: no
やってることは、サービスの起動と停止、設定ファイルの作成と内容の追記、yumのリポジトリ追加とパッケージのインストールなどです。
書き方なんですが、YAML形式となっていてインデントなどの位置が重要ですので自分で作成するときはご注意ください。
内容が長く読むのが大変だと思いますが、中身の解説に入りたいと思います。
- name: setup Containerd
  hosts: continard
  remote_user: root
この部分は処理を行わせる対象の指定と処理を行うユーザーの指定となります。
『name: 』プレイブックの名前を設定しています。
『hosts: 』で inventry ファイルに記載したどのホストを対象にするのかを指定しています。
『remote_user: 』対象にアクセスしに行く際のユーザーを指定しています。

『tasks:』以降からが実際に行ってもらう作業の内容になります。
『- name: 』で各処理に名前を付けています。 どこでエラーになったのかなどを確認する際に重要になるので重複する名前は避けたほうがいいです。
  tasks:
  - name: Swap Stop
    shell : swapoff -a
    shell : sed -i '/centos-swap/s/^/# /g' /etc/fstab
k8s の要件でスワップを停止しています。
  - name: SElinux Disable
    ansible.posix.selinux: state=disabled
    become: true

  - name: Reboot
    ansible.builtin.reboot: reboot_timeout=600
    become: true
余計なことをされると困るので、SElinux を停止します。
『ansible.posix.selinux:』モジュールを使って、設定を変更しています。
disabledにするには再起動が必要(しないと permissive)なので『ansible.builtin.reboot:』を入れています。
  - name: FW Stop
    service:
      name: firewalld
      state: stopped
      enabled: no
『service:』モジュールを使ってファイアウォールを止めています。
本来は K8s の必要ポートを開放するのですが検証環境なのでこうしました。
  - name: kernel module file create
    file:
      path: /etc/modules-load.d/containerd.conf
      state: touch

  - name: kernel module file add line
    lineinfile:
      dest: /etc/modules-load.d/containerd.conf
      line: "{{ item }}"
    with_items:
      - "overlay"
      - "br_netfilter"

  - name: kernel module Load
    shell : modprobe overlay
    shell : modprobe br_netfilter
『file:』モジュールを使って、/etc/modules-load.d/containerd.conf を作成
『lineinfile:』モジュールを使って、作成したファイルに "overlay" と "br_netfilter" を追記しています。
『shell :』モジュールを使って、modprobe を実行し読み込んでいます。
  - name: kernel parameter file create
    file:
      path: /etc/sysctl.d/99-kubernetes-cri.conf
      state: touch

  - name: kernel parameter file add line
    lineinfile:
      dest: /etc/sysctl.d/99-kubernetes-cri.conf
      line: "{{ item }}"
    with_items:
      - "net.bridge.bridge-nf-call-iptables  = 1"
      - "net.ipv4.ip_forward                 = 1"
      - "net.bridge.bridge-nf-call-ip6tables = 1"

  - name: System Reload
    shell : sysctl --system
こちらも同様に『file:』でファイルを作成し、『lineinfile:』で追記をして、『shell :』で読み込むコマンドを実行しています。
  - name: Package Install
    yum:
      name: yum-utils
      name: device-mapper-persistent-data
      name: lvm2
『yum:』モジュールを使って、必要なパッケージのインストールをしています。
  - name: containerd add repository
    shell : yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Containerd をインストールするためのリポジトリを追加しています。
お気づきかもしれませんが Docker を入れるときのリポジトリと同じです。
実はContainerd も Docker社が作ってたものなのです。
  - name: Containerd Install
    yum:
      name: containerd.io

  - name: containerd Setting folder create
    file:
      path: "/etc/containerd"
      state: directory

  - name: containerd Setting file create
    shell : containerd config default | sudo tee /etc/containerd/config.toml

  - name: containerd Restart
    service:
      name: containerd
      state: restarted
      enabled: no
Containerd をインストールして、設定を入れるためのファイルを作成し、内容を追記してサービスを起動しています。

というわけで内容の説明はここまでです。
本当は設定変更後に、その設定を確認するコマンドを打って『register:』に格納して『debug:』で表示するとかも入れようかと思ったんですが、さすがに長くなりすぎるので次回以降で説明するタイミングがあったら入れたいと思います。

プレイブックの他に、ホストの情報を記入する hosts ファイルも修正しなければなりません。
「/etc/ansible」配下の hosts に以下のような内容を追記します。
xxx.xxx.xxx.xxx には Ansible からアクセスを行う対象のIPアドレスを入れてください。
[continard]
demo-server   ansible_host=xxx.xxx.xxx.xxx
実際に、実行してみましょう。
以下のコマンドで実行できます。
# ansible-playbook containerd-set.yaml
・・・どうでしょうか。
人によってはエラーになると思います。
というのもですね、sshでアクセスしますのでそのサーバーに初回アクセスする状態だと認証ではじかれちゃうんですよね。

というわけで、そうなっちゃった方は以下のコマンドでsshの鍵を渡してあげましょう。
xxx.xxx.xxx.xxx には Ansible からアクセスを行う対象のIPアドレスを入れてください。
# ssh-copy-id root@xxx.xxx.xxx.xxx
その後改めて実行してみてください。
そもそものプレイブックの書き方でエラーになってしまう場合は、インデントのズレなどがないか確認してみてください。

うまく処理ができた方は、Containerd をインストールしたマシンにログインして以下のコマンドを実行してください。
バージョン情報が確認できると思います。
# ctr -v
ctr containerd.io 1.6.9
これで kubernetes の構築を行う準備が整った状態となりました。 次回のブログ(来月)はいよいよ kubernetesK8s の構築を Ansible で行っていきたいと思います。 ただ、年末なのでいろいろ忙しく確認の時間が取れなかったりしたら1月のブログ投稿になるかもしれません。

2022年10月31日月曜日

やってみよう自動化ツール Ansible その1 Ansible ってどんなもの? インストールはどうやるの?

今回から、自動化ツールの Ansible を使用して今まで手動で作ったものを自動で作ってみるシリーズを開始したいと思います。
どんなことをやるかといいますと、K8s を Ansible で自動構築してそこに MetalLB なんか立ててみたいな~ って思っています。

今回は、まず Ansible ってどういうものなのかと、どうやって使うかの説明を行います。
ドキュメントは以下となっています。


https://docs.ansible.com/ansible/2.9_ja/index.html

Ansible は Ansible をインストールしたマシンから、作業を行いたいマシンへ ssh で接続します。
どうやって作業を行うかというと、playbook という作業内容を書いた yml 形式のファイルを用意します。
この yml ファイルを指定することで、作業を行ってもらうわけです。

ansibleの設定ファイルなどは、インストールしたホストの「/etc/ansible」に置かれます。
ls コマンドで確認してみると設定ファイルの ansible.cfg とアクセスするホストの情報を記入する hosts 個別に処理を用意して呼び出せるようにする role 用のディレクトリがあります。

全ての作業を一つの yml に書いて作業を行うことも可能ですが、いろんなサーバーを構築する場合でも同じ処理というものは発生すると思います。
ホスト名の設定や必ずインストールする必要があるものなどです。
そういう場合に処理をあらかじめ書いておいて必要な処理だけを呼び出してつかえるのが「roles」になります。

全体の処理をスタートさせる yml があって、その中にどの「roles」を呼び出すかという処理を書きます。
「role」ディレクトリ配下に作成したディレクトリ名がyamlで呼び出すときに指定するの名前となり、そのディレクトリに行いたい処理を記載した yml を配置する形になります。
例として、ホスト名設定、必要パッケージのインストール、という処理を roles を使用した際のファイル配置は絵でかくとこんなイメージです。

全体処理のyml
 |
 |― 「roles」←ディレクトリ
     |
     |―「OS_Setup」←ディレクトリ
     |   |
     |   |―「tasks」←ディレクトリ
     |   |     |    
     |   |     |― main.yml(ホスト名設定の処理を書いた yml )
       |
       |
     |―「Package_Insutall」←ディレクトリ
         |
         |―「tasks」←ディレクトリ
                 |         
                |― main.yml(必要パッケージのインストール処理を書いた yml )


「main.yml」となっているのは、各ディレクトリの「main.yml」を読み込むように設定されているためです。
全体の yml にはどのロールを使うのかの指定を行うフィールドを書いて「OS_Setup」や「Package_Insutall」のディレクトリ部分を指定します。
※本当は「tasks」と同列に「handlers」と「templates」というディレクトリも行わせる処理によって用意します。

とまぁ、複雑なこともできるようになっているので Ansible は使えるようになっておいて損はないと思います。
構築だけでなく繰り返し同じ処理を行うようなテストでも使えそうですからね。

とはいえすぐにいろいろ機能を使ったものを作るのも理解するのも無理なので、まずは基本となる1つの yml に全部を書く形でやってみましょう。
最後はそれを元に roles に分解していきたいと思います。

では、Ansible のインストールをしてみましょう。
ホストOSはCentos 7 を使います。
公式マニュアルはこちら
https://docs.ansible.com/ansible/2.9_ja/installation_guide/intro_installation.html

yum でサクッとインストールするのですが、リポジトリが epel の様なのでそちらをインストールします

# yum install epel-release

リポジトリが使えるようになったので Ansible をインストールしましょう

# yum install ansible

インストール自体はこれで完了です。
確認として ansible のバージョンを表示してみましょう
# ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]


このように出力されていれば成功です。
次回は、Docker と同様にコンテナを動かすことができる containerd のインストールを ansible で行う playbook の作成をやってみようと思います。

2022年9月30日金曜日

調べてみようコンテナセキュリティ その6 ~Harborつかってみた~

 前回はHarborの構築を行いました。

今回はHarborにログインしてイメージのプッシュを行いたいと思います。


まずはGUIからログインしてみましょう。

ちなみに、adminの初期パスワードは harbor.yml に記載があります。

ログインしてみると「library」というプロジェクトが1つだけある状態です。


「library」をクリックしてみると、当然ながら何もありません。

今回は、ここにイメージを追加する作業を行うのですがその前に1つやっておきたいことがあります。


今回は前回構築したHarbor用のサーバーからイメージのアップロードを行うのでこの作業を必要としませんが、他のマシンからイメージをアップロードしようとする場合に証明書が必要となりますのでその証明書をダウンロードできるリンクを用意します。

実は、設定してあるとこの画面に表示されるのです。


何をするかというと、Harborのサーバーに「/data/ca_download/」に証明書を置いてあげるのです。

証明書関係のファイルはいっぱいありますが、拡張子が ca.crt となっているものがそうなります。

前回構築した環境ですと、以下のコマンドで配置できます。

# cp /root/CA/ca.crt /data/ca_download/


ブラウザを更新すると「REGISTRY CERTIFICATE」というリンクが出てきます。

これで証明書をGUIからダウンロード可能になりました。

では続いて、一旦GUIからは離れコマンドラインでの操作となります。


docker login コマンドを使用して Harbor へログインします。

# docker login <harborのIPアドレスかFQDN> -u admin -p <パスワード>


CUI のログインができたところで、GUI に戻ります。

先ほどの画面で、「PUSH COMMAND」というリンクがありますのでそちらをクリックします。

Harbor のリポジトリにpushを行うために、TAG を付ける命名規則と push の際のコマンドが表示されます。


これに従ってまずイメージの TAG 付けを行いましょう。

こちらは docker tag コマンドを使用します。


現在ローカルに保存してあるイメージは docker images で表示できるので好きなものを TAG 付けします。

ちなみにこの時、Harbor で使用されているイメージも確認できます。

ここでは CentOS 7 を利用します。


# docker tag centos:7 <HarborのIPアドレスかFQDN>/library/centos:harbor-test

このコマンドは、元となるイメージを指定(centos:7)し、付与するTAGを指定された命名規則に従って<HarborのIPアドレスかFQDN>/<転送するプロジェクト名>/<任意のイメージ名:任意のTAG名>となっています。


それでは push します。

# docker push <harborのIPアドレスかFQDN>/library/centos:harbor-test


ブラウザを更新すると、以下の様に push されたイメージが表示されます。

イメージを確認してみると、「Tags」に先ほどアップロードした tag 情報も確認することができます。


push ができたので pull してみましょう。

「Tags」のとなりに「Pull Command」がありますのでクリックしてコピーしてCUIで実行できますが、実行前にローカルに存在しているイメージを消しておいた方がわかりやすいと思います。

以下のコマンドで削除してみましょう


docker rmi <harborのIPアドレスかFQDN>/library/centos:harbor-test


先ほどコピーしたコマンドを確認すると、@sha256:~~~~ と追加されている部分があると思います。

これはダイジェストというそのイメージに付与された普遍的な識別子です。

これを付けることで、確実にそのイメージをダウンロードすることができるという事ですね。

実際にやってみましょう。


docker pull <harborのIPアドレスかFQDN>/library/centos@sha256:xxxxxx~~~~


ダイジェストを使ってダウンロードしてきたイメージは、tagが付与されていません。

そのため docker tag コマンドを使用して tag を付与することになりますが、イメージの指定にはイメージの名前ではなく「IMAGE ID」を使用します。


docker tag <IMAGE ID> <harborのIPアドレスかFQDN>/library/centos:harbor-test


先ほどまで none だった tag が付与されたと思います。


これで、イメージを検査しプライベートなリポジトリを用意してそこへイメージを push し pull して使うことができるようになりました。


コンテナのセキュリティに関してはこれで一旦終わりとしたいと思います。

読んでくださった方々ありがとうございました。


次は、今まで作ったものを自動で構築とかしてみましょうかね。

以前書いたk8sの構築もdockerではできなくなりましたし、その辺も絡めたりとか。

もしくは、Tanzu製品があれよあれよとたくさん増えて何する製品なのかが分からなくなってきたので、それぞれどういう事を目的とした製品で何ができるのかをまとめた記事を書こうかと考えています。

2022年8月31日水曜日

調べてみようコンテナセキュリティ その5 ~harbor作ってみた~

前回までで、イメージの脆弱性や構成上の問題をチェックし対応することが可能になりました。

コンテナ用のイメージは普段DockerHubからpullしてくると思いますが、セキュリティ的な観点からプライベートなコンテナレジストリを用意したいと思うこともあると思います。

そこで、自分用のコンテナレジストリとしてharborの作成(今回)と使い方(次回)について記載したいと思います。


harborを何で作るかですが、いろんな作り方があるんですけど今回はdocker composeという複数のコンテナを管理するツールを使いたいと思います。

元になるOSは毎度おなじみCentos 7でやります。

それではやっていきましょう。


コンテナとして展開するのでdockerを使います。

まずはdockerの構築が必要ですが、ここではdockerの構築は省略させていただきdocker-composeの構築からやっていきたいと思います。


利用するdocker-composeとharborのバージョンは以下

 [バージョン]

  - docker-compose v2.5.1

  - harbor v2.5.1


まず、docker composeの導入です。

手順はこちら。

https://docs.docker.jp/compose/install.html#linux


・利用するv2.5.1を指定してコマンドを実行します。

 # curl -L https://github.com/docker/compose/releases/download/v2.5.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

 # chmod +x /usr/local/bin/docker-compose


・バージョンの確認をします。

 # docker-compose version

 # Docker Compose version v2.5.1


docker composeはこれで準備完了です。

驚きの簡単さですね。


続いてharborになります。

こっちは、証明書の作成やそれに合わせたファイルの書き換えなどがあるので手順も多くしんどいです。

それゆえに、うまくいかないことも多いですので心を強く持って挑んでください。


まずはharborのバイナリをダウンロードしてきて、構築用のOSに転送します。

開発速度が速いので、今回記載しているバージョンより新しいものが出ているかと思いますが、その場合でもおそらく構築手順自体は同じだと思います。

今回は/root直下でやっています。

  - harborのバイナリダウンロード先

      - https://github.com/goharbor/harbor/releases

        使いたいバージョンの「Assets」からダウンロードできます。


・CentOS上で解凍します。今回は/root 直下

 # tar zxvf harbor-offline-installer-v2.5.1.tgz


証明書関連の作成に着手します。

これは正しく作成配置ができていないと、イメージを置いたりダウンロードしたりするときに認証が通らなくて失敗します。

個人的にはこれに一番苦労しました。


・作業用のディレクトリを作成し移動ます。

 # mkdir CA

 # cd CA


・CA証明書の秘密鍵を生成します。

 # openssl genrsa -out ca.key 4096


・CA証明書を生成 ※CNにharborホスト名をFQDNで入れます

 # openssl req -x509 -new -nodes -sha512 -days 3650 \

  -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=xxxx.xxxx" \

  -key ca.key \

  -out ca.crt


・秘密鍵を生成します。

 # openssl genrsa -out myharbor.key 4096


・証明書署名要求(CSR)を生成します。

 # openssl req -sha512 -new \

     -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=xxxx.xxxx" \

     -key myharbor.key \

     -out myharbor.csr


・x509v3拡張ファイルを生成します。

 # cat > v3.ext <<-EOF

 authorityKeyIdentifier=keyid,issuer

 basicConstraints=CA:FALSE

 keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment

 extendedKeyUsage = serverAuth

 subjectAltName = @alt_names


 [alt_names]

 IP.1=OSのIPアドレスを入力

 DNS.1=harborホストのFQDNを入力

 DNS.2=harborホストのショートネームを入力

 EOF


・このファイルを使用してv3.ext、harborホストの証明書を生成します。

 # openssl x509 -req -sha512 -days 3650 \

     -extfile v3.ext \

     -CA ca.crt -CAkey ca.key -CAcreateserial \

     -in myharbor.csr \

     -out myharbor.crt


・ホストにサーバー証明書と秘密鍵を置きます。

 # mkdir -p /data/cert/

 # cp myharbor.crt /data/cert/

 # cp myharbor.key /data/cert/


・サーバー証明書、秘密鍵、CAファイルをharborホストのDocker証明書フォルダーにコピーします。

 # mkdir -p /etc/docker/certs.d/harborホストのFQDN/

 # cp myharbor.key /etc/docker/certs.d/harborホストのFQDN/

 # cp ca.crt /etc/docker/certs.d/harborホストのFQDN/


・harborの設定ファイルharbor.ymlに必要な情報を記入します。

 テンプレート(harbor.yml.tmpl)があるのでコピーして.ymlにします。

 # cd ../harbor

 # cp harbor.yml.tmpl harbor.yml

 # vi harbor.yml


 編集個所は以下

 # Configuration file of Harbor

 # The IP address or hostname to access admin UI and registry service.

 # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.

 hostname: reg.mydomain.com ※harborホストのFQDNに変更


 # http related config

 http:

   # port for http, default is 80. If https enabled, this port will redirect to https port

   port: 80

 

 # https related config

 https:

   # https port for harbor, default is 443

   port: 443

   # The path of cert and key files for nginx

   certificate: /your/certificate/path ※/data/cert/myharbor.crt に変更

   private_key: /your/private/key/path ※/data/cert/myharbor.key に変更


・インストールのスクリプトを実行します

 # ./prepare

 # ./install.sh


・ブラウザから以下へ接続を確認します。

 http://harborホストのIPアドレス

 

これで構築は完了です。

作業が多く何を作ってるのか見失いがちになりますが、ゆっくり一つ一つやっていきましょう。

初めて作るときはチェックシートなんかを用意してみてもいいかもしれませんね。


次回は、出来上がったharborへログインしてイメージのpushやpullを実行してみましょう。

2022年7月29日金曜日

調べてみようコンテナセキュリティ その4 ~dockle 使ってみた~

 今回は、dockleについてインストールして実際に使ってみたいと思います。

使ってるのはCentOS 7 なので、インストール方法はこちら。


  VERSION=$(

   curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \

   grep '"tag_name":' | \

   sed -E 's/.*"v([^"]+)".*/\1/' \

  ) && rpm -ivh https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.rpm


公式(https://github.com/goodwithtech/dockle#installation)にこれだけしか書いてないんですが、これで動くのだろうか・・・

あ、いや、動くんだとは思いますよ、OSにあったバージョンのrpmを持ってきてインストールする内容だと思いますし。

むかしは、何もわからず「こうやったら動くって書いてあるからこうやればいい」と思ってやっていましたが、いまは「こういうことをするんだろうなこのコマンドで」とある程度はわかるようになってきたので、長い年月続ける意味ってあるんだなぁって・・・


では、やっていきましょう

実行すると以下のような出力が出てインストールが実行されます。

  https://github.com/goodwithtech/dockle/releases/download/v0.4.5/dockle_0.4.5_Linux-64bit.rpm を取得中

  準備しています...              ################################# [100%]

  更新中 / インストール中...

     1:dockle-0:0.4.5-1                 ################################# [100%]


動くものですね、結構マニュアルとかで「こうやったら動くよ」って書いてあってもそのままやったら動かないことも多く経験してきたものでいまだに動くと驚いちゃうんですよねぇ。

たいてい、「いや~、この製品使うならこういうことはやっておくのが常識でしょう???」みたいな、前提条件が省かれて手順が書かれてるようなことが多くて、この手順を成功させるために前もって必要なものがあったりしないかな?

という事を考えたり調べたりしちゃう書いてあることが信用できない悲しいSEなのです。


インストールできたので脆弱性のチェックをやっていきます。


  2022-07-22T17:09:32.027+0900    INFO    Failed to check latest version. not found version patterns

  WARN    - CIS-DI-0001: Create a user for the container

          * Last user should not be root

  INFO    - CIS-DI-0005: Enable Content trust for Docker

          * export DOCKER_CONTENT_TRUST=1 before docker pull/build

  INFO    - CIS-DI-0006: Add HEALTHCHECK instruction to the container image

          * not found HEALTHCHECK statement

  INFO    - CIS-DI-0008: Confirm safety of setuid/setgid files

          * setuid file: urwxr-xr-x usr/sbin/pam_timestamp_check

          * setuid file: urwxr-xr-x usr/bin/newgrp

          * setuid file: urwxr-xr-x usr/sbin/unix_chkpwd

          * setuid file: urwxr-xr-x usr/bin/passwd

          * setuid file: urwxr-x--- usr/libexec/dbus-1/dbus-daemon-launch-helper

          * setuid file: urwx--x--x usr/bin/chfn

          * setgid file: grwxr-xr-x usr/bin/write

          * setuid file: urwxr-xr-x usr/bin/su

          * setuid file: urwxr-xr-x usr/bin/gpasswd

          * setuid file: urwx--x--x usr/bin/chsh

          * setuid file: urwxr-xr-x usr/bin/mount

          * setuid file: urwxr-xr-x usr/bin/umount

          * setuid file: urwxr-xr-x usr/bin/chage

          * setgid file: grwx--x--x usr/libexec/utempter/utempter

  INFO    - DKL-LI-0003: Only put necessary files

          * Suspicious directory : tmp



このチェックでの判定は5段階のようです


『Level』

  https://github.com/goodwithtech/dockle#level


いろいろ出てきましたが、trivyの時ほどいっぱい怒られませんでしたね。

どういうところで引っかかったのかは以下で確認できます。


 『Checkpoint Summary』

  https://github.com/goodwithtech/dockle#checkpoint-summary


どうやって改善したらいいのかも見ることができます。

これを参考に対処してねという事なのでしょう。


 『Checkpoint Details』

   https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md


ちょうど「WARN CIS-DI-0001」の出力がありましたので、そちらの対処を行ってみたいと思います。

今回は、イメージを作成する設計書のDockerfileと、Dockerfileの内容を読み込んでイメージを作成する docker build コマンドを使用し、修正を組み込んだイメージcentos:dockle の作成をします。

Dockerfile の中身は以下の様になります。


  ====

  # STEP1 CentOS 7 のイメージをベースにする

  FROM centos:centos7

  # STEP2 CIS-DI-0001の対処 

  RUN useradd -d /home/dockle -m -s /bin/bash dockle

  USER dockle

  ====


ではイメージを作成してみます。


  # docker build -t centos:dockle dockle/

  Sending build context to Docker daemon  2.048kB

  Step 1/3 : FROM centos:centos7

   ---> eeb6ee3f44bd

  Step 2/3 : RUN useradd -d /home/dockle -m -s /bin/bash dockle

   ---> Running in 48139360d8c8

  Removing intermediate container 48139360d8c8

   ---> 4cf2480c9454

  Step 3/3 : USER dockle

   ---> Running in 950fa59666e5

  Removing intermediate container 950fa59666e5

   ---> d5cb3dc4dd14

  Successfully built d5cb3dc4dd14

  Successfully tagged centos:dockle


出来上がったイメージがちゃんと存在するか確認します。


  # docker images

  REPOSITORY   TAG       IMAGE ID       CREATED          SIZE

  centos       dockle    d5cb3dc4dd14   16 seconds ago   204MB


では、修正を盛り込んだイメージのチェックをしてみます。


  # dockle centos:dockle

  2022-07-25T10:18:17.309+0900    INFO    Failed to check latest version. not found version patterns

  2022-07-25T10:18:19.255+0900    FATAL   unable to initialize a image struct: failed to initialize source: reading manifest dockle in docker.io/library/centos: manifest unknown: manifest unknown


エラーとなってしまいました。

メッセージを検索等してみたところ、どうやらローカルにあるイメージをスキャンしたいんだけど実際はリモート(docker hubかな?)にスキャン対象イメージを探しに行ってしまっているということみたいです。

その対処は以下にありました。


  『Use Docker』

    https://github.com/goodwithtech/dockle#use-docker


dockleのコンテナを起動してスキャンしてもらって、結果が出たらdockleのコンテナは削除するという使い方のようですね。

ここに「You only need -v /var/run/docker.sock:/var/run/docker.sock when you'd like to scan the image on your host machine.」と記載があり、ローカルにあるイメージををスキャンするときはこうする必要があるみたいです。

では、コマンドを今回の環境に合わせて、バージョンとイメージを指定したいと思います。


バージョンの確認


  # dockle -v

  dockle version 0.4.5


コマンドはこうなりました。


  # docker run \

      --rm \

      -v /var/run/docker.sock:/var/run/docker.sock \

      -v $(pwd)/.dockleignore:/.dockleignore \

      goodwithtech/dockle:v0.4.5 \

      centos:dockle


実行してみたいと思います。


  Unable to find image 'goodwithtech/dockle:v0.4.5' locally

  v0.4.5: Pulling from goodwithtech/dockle

  97518928ae5f: Pull complete

  fc586ee9e6b2: Pull complete

  Digest: sha256:ebd36f6c92ac850408c7cbbf1eddf97e53565da9d661c5fb8ec184ad82a5358d

  Status: Downloaded newer image for goodwithtech/dockle:v0.4.5

  2022-07-25T01:41:20.053Z        INFO    Failed to check latest version. not found version patterns

  INFO    - CIS-DI-0005: Enable Content trust for Docker

          * export DOCKER_CONTENT_TRUST=1 before docker pull/build

  INFO    - CIS-DI-0006: Add HEALTHCHECK instruction to the container image

          * not found HEALTHCHECK statement

  INFO    - CIS-DI-0008: Confirm safety of setuid/setgid files

          * setuid file: urwxr-xr-x usr/bin/chage

          * setuid file: urwxr-xr-x usr/bin/passwd

          * setuid file: urwxr-xr-x usr/bin/su

          * setuid file: urwxr-xr-x usr/sbin/unix_chkpwd

          * setuid file: urwxr-xr-x usr/bin/umount

          * setuid file: urwx--x--x usr/bin/chfn

          * setuid file: urwxr-xr-x usr/bin/gpasswd

          * setuid file: urwxr-xr-x usr/sbin/pam_timestamp_check

          * setuid file: urwx--x--x usr/bin/chsh

          * setuid file: urwxr-xr-x usr/bin/newgrp

          * setgid file: grwxr-xr-x usr/bin/write

          * setuid file: urwxr-x--- usr/libexec/dbus-1/dbus-daemon-launch-helper

          * setgid file: grwx--x--x usr/libexec/utempter/utempter

          * setuid file: urwxr-xr-x usr/bin/mount

  INFO    - DKL-LI-0003: Only put necessary files

          * Suspicious directory : tmp


修正を盛り込んだことで「WARN CIS-DI-0001」の出力がなくなりました。

trivyとdockleを組み合わせて、より強固で安全なイメージの作成ができそうですね。


次回は、せっかく作ったイメージを置いておくコンテナレジストリを自分で作って使ってみるという事をやりたいと思います。

2022年6月30日木曜日

調べてみようコンテナセキュリティ その3 ~trivy使ってみた~

今回はコンテナイメージの脆弱性を確認してくれるtrivy編となります。


実際にインストールをしてみましょう。

まずはtrivy をyum でインストールするための作業です。


1.使ってるOSのバージョンを変数に入れます。
# RELEASE_VERSION=$(grep -Po '(?<=VERSION_ID=")[0-9]' /etc/os-release) 


2.1.の値を使ってyumのレポジトリを追加します。
# cat << EOF | sudo tee -a /etc/yum.repos.d/trivy.repo
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$RELEASE_VERSION/\$basearch/
gpgcheck=0
enabled=1
EOF


3.一旦全体のUpdateをおこないます。
# sudo yum -y update


4.trivyをインストールします。
# sudo yum -y install trivy


これでインストールできたようです。

コマンドを打ってみましょう・・・のまえに、スキャンするイメージが必要なので適用にCentos7でもイメージを引っ張っておきましょう。
# docker pull centos:centos7


それでは、trivyによるコンテナイメージのスキャンを実施です。
# trivy i centos:centos7


実行結果がかなり長く全部乗せられませんので見づらいかもしれないですがスクショを・・・








思ってたよりは全然きれいにテーブル表示形式で出力が見れました。

一番左が対象となるもので、そこからCVEの何に該当しているか、脆弱性の深刻さ、インストールされているバージョン、問題が解決しているバージョン、一番右はCVEのタイトルですかね。

で、これってどうやって対処するんでしょうと思ったあなた。
私も当然思いました。
仮になんですが、このイメージから展開したコンテナにログインしてyum update でもすればいいんでしょうか?(権限的にできる?
ま、とりあえずやってみましょ。

コンテナを起動します。
# docker run -d -i -t centos:centos7 /bin/bash

コンテナにログインするため、CONTAINER IDを確認します。
# docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED         STATUS                             PORTS                       NAMES
8c70ec6e46e2   centos:centos7                       "/bin/bash"              6 minutes ago   Up 6 minutes                                                   eager_mclean

コンテナにログインしてyum update を実行します。
# docker exec -i -t 8c70ec6e46e2 /bin/bash
# yum update -y


先ほど「HIGH」で表示されていた「bind-license」もUpdateされていることが確認できました。
# cat /var/log/yum.log | grep bind
Nov 13 01:55:50 Erased: 32:bind-utils-9.11.4-26.P2.el7.x86_64
Nov 13 01:55:51 Erased: 32:bind-libs-9.11.4-26.P2.el7.x86_64
Nov 13 01:55:51 Erased: 32:bind-libs-lite-9.11.4-26.P2.el7.x86_64
Jun 09 01:36:23 Updated: 32:bind-license-9.11.4-26.P2.el7_9.9.noarch


yum update -y できたので、一旦exit でコンテナから抜けます。

この状態でイメージスキャンをしても、変更が保存されていないイメージしかいないため結果は変わりません。


そのため、docker commit で更新したコンテナから新しくイメージを「centos:update」として作成します。
# docker commit 8c70ec6e46e2 centos:update
sha256:6bc0f6964c196dc38a3b00bcf79a9b586306253808b08e8e26b16c80290831fc


作成されたものを確認してみると、SIZEが増えているのでちゃんとyum update の内容が反映されてそうですね。
# docker images
REPOSITORY                      TAG       IMAGE ID       CREATED              SIZE
centos                          update    6bc0f6964c19   About a minute ago   510MB
centos                          centos7   eeb6ee3f44bd   8 months ago         204MB


では改めて作成したイメージをスキャンしてみましょう。
# trivy i centos:update










Fixed Version があったものが全部表示されなくなったようですね。

アップデートで解消できる問題については、trivyで発見と対応後の状態を確認できることは確認できました。

ちょっと長くなってしまったので、dockleは次回に回したいと思います。


2022年5月31日火曜日

調べてみようコンテナやPodのセキュリティ その2 ~コンテナイメージの脆弱性確認ツールについて~

 コンテナイメージの脆弱性確認ツールについて


こちらは、コンテナのセキュリティに関して勉強していくシリーズの第2回となっています。

今回は、コンテナイメージの脆弱性確認ツールについて調べたことを書いていこうと思います。


コンテナイメージというものは、実はWindowsやCent OSのインストール時に使うisoとかと違って動かすアプリケーションに必要なファイルやディレクとりなどの階層が固められたものになります。

コンテナはホストOSのカーネルを利用するので、それ以外の部分で動かすアプリケーションに必要なものが固められたものがコンテナイメージというわけです。

なので、一般的なウイルス対策ソフトでファイルのスキャンをするというのとはちょっと内容が違ってきます。


一般的なウイルスソフトのスキャンは、スパイウェアやマルウェアの発見と駆除をしてくれます。

コンテナイメージでも同じようにファイルに問題がないか、変なプログラムがいないか、と言ったことをスキャンしてくれるのかというとそうではありません。

簡単に言いますと、イメージの中にあるアプリケーション等が既存の脆弱性(CVE)に該当していないかどうかという事を報告してくれます。


ここで覚えておいてほしいのが、脆弱性を報告してくれますがその対処は人間が行うという点です。

スパイウェアやマルウェアの駆除をしてくれる一般的なウイルスソフトは自動で駆除なり隔離なりをしてくれると思いますが、コンテナイメージの場合は人間が対処を行って大丈夫な状態のコンテナイメージを作成する必要があるという事ですね。

システム任せにできないのでかなり大変になりそうだなと思いました。


コンテナイメージのスキャンで有名なのが、Trivyという製品です。

先ほどの脆弱性に該当してないかどうかの確認と、設定ファイルの不備もチェックしてくれるようです。

こういったものが一般的に使われているようですね。


最初はTrivyを調べて記事にしようかと思ったんですが、これとはちょっと違うDockelというものもあるようでせっかくなら比較してみようかと思いました。

Dockelもコンテナイメージの脆弱性を確認してくれるツールなのですが、こちらはCIS Benchmark というシステムを安全に構築するためのベストプラクティスがありまして、そちらのコンテナに関係する部分についてもチェックを行ってくれるようです。


次回は実際にやってみた結果でブログを書きたいと思いますが、もしかしたらどちらか一方の記事になるかもしれません…

2022年4月28日木曜日

調べてみようコンテナやPodのセキュリティ

 今回から、Podやコンテナのセキュリティについて学習したことをまとめていきたいと思います。

なぜそんなことをしようと思ったのかといいますと、たまたまPodを実際に外部公開して使いましょう

となった場合、セキュリティの考え方は従来通りでいいんだろうか?


Podやコンテナにアンチウィルスソフトとかって入れるの? それってどうなんだろ?

という事を考えて気になり始めたので、実際に調べてみたところだいぶ考え方が違うしやる事も違う

という事がわかったためです。


従来のWindows OSなどでは、パッチを適用したりアンチウィルスを入れてスキャンしたり、ファイアウォールで

防御したりという事がセキュリティ的な対応としてすぐに思いつく事ではないでしょうか。

しかし、コンテナやPodでは少々事情が異なります。


コンテナやPodというのは、使いたいOSやアプリのイメージを使用して構築します。

この時に、脆弱性のチェックを行って脆弱性の対応が済んでいる状態のイメージを使用することで脆弱性の対応を

完了してしまうのです。


時間がたてば、新しい脆弱性等が発見されたりしますので、その際は対応を行ったイメージを再度作成しそれを利用する。

こういった作業を繰り返すのがPodやコンテナにおける脆弱性への対応の一つとなります。

使うイメージの状態に問題がなければ大丈夫という考え方という事ですね。


外部からアクセスされて乗っ取られたらどうするかという部分については、コンテナやPod内で動くユーザーを、非root

権限のユーザーにするといった対応を行っていくことになります。


今後、このブログでは、イメージの脆弱性を確認するツール、イメージのマルウェアを確認するツール、外部リポジトリ

を使用した脆弱性対応などについて調べたり確認したことを書いていこうと思いますので、ご興味ありましたら読んでみてください。

2022年2月25日金曜日

俺とkubernetesと時々vSphere -DeploimentとStatefulsetについて-

このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や

相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


今回は、Podの展開を行う方法である『Deploiment』と『Statefulset』という

リソースの違いについてご説明したいと思います。


Deploiment


 Deploimentは、展開するPodの数を決めて一度に複数のPodを展開することができます。

 vSphereで考えると、一つのテンプレートから複数の仮想マシンをグループとして

 一度に作成するようなイメージでしょうか。


 ただ、PVCを利用した場合、すべてのPodで同じ領域を使用するため個別にデータを

 残しておきたいようなアプリケーションには不向きとなります。


 ただ単にプリケーションを実行したいとか、Webサーバーにしておきたいとかそう

 いった用途のPodはこの方式でよく作られていると思います。

 ※仮に残しておきたいデータがあった場合は、定期的に外部にデータを保存する仕組み

  を持たせていると思います。


Statefulset


 Statefulsetも、展開するPodの数を決めて一度に複数のPodを展開することができます。

 Deploimentとの違いは、こちらはPVCを使用することでPod毎にデータ絵領域を持たせる

 ことができる点です。


 データベースなど、個別に情報を残しておく必要があるPod用の展開方式となります。


大きな違いは上記となります。

また、単体のPodではなく、DeploimentやStatefulsetとして展開することで、得られる

以下の様なメリットもあります。


 ・必要展開数の保持

  展開したPodに何かしら問題が発生して正常に動いているPodの数が設定したPodの数に

  足りなくなった場合、自動的にPodを展開して正常に稼働しているPodの数を保ちます。 

  

 ・Podの展開数調整が容易(スケールアウト、スケールイン)

  yamlに記載するPod展開数を変更し、再度kubectl applyすることで数を増やしたり

  減らしたりがすぐにできます。


 ・ローリングアップデート

  yamlファイルに変更があって更新されたことを感知すると、新しいyamlファイルで

  展開したPodと入れ替えてくれる機能。

  1台づつ入れ替えてくれるので、提供しているサービスは停止しない優れもの。


     どうやって、ローリングアップデートしているかというと。

   

  実はDeploimentもStatefulsetも内部にPodの展開をするReplicaSetというリソース

  を持っていたりします。

  それをうまく使っているということになりますが、ここでは、仮にDeploimentか

  Statefulsetで現在動いているPodたちがあったとして説明したいと思います。

    

  yamlファイルに変更が起きると、新しいyamlファイルでReplicaSetがPodを作ります。

  実は、複数のReplicaSetを管理する機能をDeploimentもStatefulset持っているので、

  古いReplicaSetと新しいReplicaSetが同時に存在しているのです。


  新しいyamlファイルでの展開が終わると、現在メインとなっている古いReplicaSetの

  Podと新しいReplicaSetのPodを1台入れ替えてくれます。

     この動作を必要なPod台数分実施することで、提供しているサービスを止めることなく

  Podアップデートを行えるようにしているわけです。


次回は実際にStatefulsetを展開とローリングアップデートを確認してみたいと思います。

2022年1月31日月曜日

俺とkubernetesと時々vSphere -動的PVCの利用について その2-

このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や

相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


今回はPodのストレージ周りのお話の続きとなります。

Podがデータを保存するために追加するPod用の外部ストレージ、PersistentVolumeを自動的に作ってくれる動的PVCの導入です。


今回は、nfs-clientを導入しNFSで動的PVCを使えるようにします。

そのため、ノードとなっているOSに/NFSという領域を作って、そこにCentOSで作成したNFSサーバーをくっ付けて使います。

気を付けていただきたいのは、Kubernetesクラスタはマスターとワーカーのノードがあり、Podはワーカーで動くのでワーカーとなっているサーバーにNFSをマウントしておかないとPodがNFSの領域を使えません。


うっかりマスターにだけ追加して、あれ? PV作られないじゃん??? とならないようご注意ください。(n敗

では、すべてのノードにNFSがマウントされている状態を前提として、nfs-clientの導入手順を紹介したいと思います


nfs-clientの導入方法はいくつか方法がありますが、簡単なのでhelmを使って導入したいと思います。

helmは、Kubernetes用のyamlみたいなものです。

これを使うと、Kubernetes上にアプリケーションのPodを展開してくれます。


作業自体は、マスターノードで行います。

まず、helmを使えるようにします。

  curl -O https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3

  ls

  bash ./get-helm-3


nfs-clientを導入するためhelmのレポジトリ追加

  helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/


nfs-clientインストール

  helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \

  --set nfs.server=192.168.0.5 \

  --set nfs.path=/nfs


        nfs.server → NFSサーバーのIPアドレス

        nfs.path → NFSサーバー側で共有しているディレクトリ


※なんかうまくいかなくてアンインストールする場合は以下

  helm uninstall nfs-subdir-external-provisioner


何ができたかの確認

  # kubectl get pod

  NAME                                              READY   STATUS    RESTARTS   AGE

  nfs-subdir-external-provisioner-59479459d5-qbbdv   1/1     Running   0          22h


  # kubectl get sc

  NAME         PROVISIONER                                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE

  nfs-client   cluster.local/nfs-subdir-external-provisioner   Delete          Immediate           true                   5m43s


nfs-subdir-external-provisionerのPodとStorageClassが作成されます。

このnfs-clientという名前で作られたStorageClassを指定してPVCを作成すると自動でPVを作ってくれるというわけです。


実際にやってみましょう!

こんな感じでyamlを用意します。


確認用のPVC作成例

 pvc.yaml

  ----

  apiVersion: v1

  kind: PersistentVolumeClaim

  metadata:

    name: my-provisioner

    annotations:

      # ここでStorageClass の名称を指定

      volume.beta.kubernetes.io/storage-class: nfs-client

  spec:

    accessModes:

      - ReadWriteOnce

    resources:

      requests:

        # ここでリクエストするボリュームサイズを決定

        storage: 5Gi

  ----


PVCの作成

  # kubectl apply -f pvc.yaml


作成したPVCを確認する

  # kubectl get pvc

  NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE

  my-provisioner   Bound    pvc-4b8ca59d-28cf-4f2d-a078-e8392bde5a81   5Gi        RWO            nfs-client     36s


PVCを作成すると、NFS側に以下の命名規則でディレクトリが作成される。


   ${namespace}-${pvcName}-${pvName}


   ※ここの例では以下のディレクトリがNFSサーバー側にできる


     default-my-provisioner-pvc-4b8ca59d-28cf-4f2d-a078-e8392bde5a81


当然PVも自動で作成される。

  # kubectl get pv

  NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE

  pvc-4b8ca59d-28cf-4f2d-a078-e8392bde5a81   5Gi        RWO            Delete           Bound    default/my-provisioner   nfs-client              46s             15s



このPVCを要求するPodを作成する


確認用のPVC作成例

  test-pod.yaml

  ----

  apiVersion: v1

  kind: Pod

  metadata:

    name: my-mginx

  spec:

    containers:

      - name: my-mginx

        image: nginx

        ports:

          - containerPort: 80

            name: web

        volumeMounts:

        - mountPath: /usr/share/nginx/html  #インデックス用ファイルを後で置いて確認する予定

          name: nginx-pvc

    volumes:

      - name: nginx-pvc

        persistentVolumeClaim:

          claimName: my-provisioner # 作成した PVC 名

  ----


Podの作成

  # kubectl apply -f test-pod.yaml


作成したPodはnginxなのでアクセスして状態を確認するため、IPアドレスを確認する。

  # kubectl get pod -o wide

  NAME                                              READY   STATUS    RESTARTS   AGE     IP             NODE                      NOMINATED NODE   READINESS GATES

  my-mginx                                           1/1     Running   0          38s   10.244.2.5   snt-k8s-node2.snt.local   <none>           <none>

  nfs-subdir-external-provisioner-59479459d5-qbbdv   1/1     Running   0          13m   10.244.1.4   snt-k8s-node1.snt.local   <none>           <none>


確認できたIPアドレスにcurlでアクセスすると、以下の表示になる。


  # curl 10.244.2.5

  <html>

  <head><title>403 Forbidden</title></head>

  <body>

  <center><h1>403 Forbidden</h1></center>

  <hr><center>nginx/1.21.6</center>

  </body>

  </html>


NFSサーバー側にできたディレクトリ(PV)にインデックスファイルを置いて表示される内容が期待した通りになるか確認。


  まず、PVの領域に移動 # cd /mnt/default-my-provisioner-pvc-4b8ca59d-28cf-4f2d-a078-e8392bde5a81/


  ファイルはこのコマンドで作成 # echo "nfs-clint TEST" > index.html


  ファイルができてるか確認 # ls


再びcurlでアクセスし、nfs-clint TEST が表示されることを確認。

  # curl 10.244.2.5

  nfs-clint TEST


自動でPVCからPVが作られ、その領域にPodからちゃんとアクセスできていることが確認できた。

ということで、nfs-clientを導入し動的PVCが使えるようになりました。

これがあるとステートフルセットというPodの作り方ができるので、現在一般的なpodの作り方である

デプロイメントと合わせてそれぞれのPodの作り方と違いを解説したいと思います。

2021年12月31日金曜日

俺とkubernetesと時々vSphere -動的PVCの利用について その1-

このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や

相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


今回はPodのストレージ周りのお話となります。

Podは停止=削除となりますので、Podが停止するとPodがなくなります。

当然Podの中に蓄えられていたデータも消えてなくなります。


データベース等のPodを停止するたびに情報がなくなってしまっては困ります。

そこで、永続ボリュームというPod外部にPod用のデータ保存領域を作成してデータを

保存しようという仕組みがあります。

Strageclass(SC)、PersistentVolume(PV)、PersistentVolumeClaim(PVC)ですね。


SCは一度定義してしまえばそうそう作り直し等の作業はないと思いますが、

PVとPVCは利用するPod毎に用意する必要があり、毎度毎度必要なサイズのPVを作って

それを要求するPVCを作ってとやっていると手間ですし、PVの数が増えると管理も大変です。


そこで、PVCで要求する内容のPVを自動で作成するというのが動的PVCと呼ばれるものです。

動的PVCが使えるかどうかは、SCでその機能が使えるかどうかとなります。

SCの機能を決めているのは、プロビジョナーと呼ばれるプラグインです。


■プロビジョナー一覧はこちら

 https://kubernetes.io/docs/concepts/storage/storage-classes/


プロビジョナーの一覧を見ると、基本的にはマネージドKubernetes毎に提供されている

プロビジョナーを使ってくださいねとなっています。

そのため、手動で構築したKubernetesでは機能として動的PVCは備えてはいません。


と、いうことでどうやったらこの機能を手動で構築したお手製Kubernetesに組み込んでいくのか

というお話です。


じつはKubernetesノードに接続したNFSサーバーを使用して動的PVCが利用可能なSCを作成可能

にしてくれる「nfs-cient」というものがあります。

こちらの導入は意外と簡単に行えますので、次回の記事でやっていきたいと思います。


2021年11月26日金曜日

俺とkubernetesと時々vSphere -ServiceのLoadBalancerタイプその2-

 このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や

相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


前回、ServiceのタイプLoadBalancerは手動で作っただけのkubernetesでは使えないこと、

このServiceと連携してくれるLoadBalancerが必要となってしまうことをお話ししました。


今回ですが、kubernetesの外にあるLoadBalancerと連携するのではなく、kubernetes上に

LoadBalancerを用意して、ServiceのタイプLoadBalancerを動かしてしまえるMetalLBを

導入してみたいと思います。


MetalLBの公式はこちら

https://metallb.universe.tf/


公式に案内されていることをやれば動いてくれます。

早速作ってみましょう。


まず、MetalLBで払い出してもらうIPアドレスのレンジを決めます。

今回は192.168.0.200-192.168.0.210としました。

以下が設定となるConfigMapのyaml内容です。

configmap.yml

----

apiVersion: v1

kind: ConfigMap

metadata:

  namespace: metallb-system

  name: config

data:

  config: |

    address-pools:

    - name: default

      protocol: layer2

      addresses:

      - 192.168.0.200-192.168.0.210

----


インストールをしていきます。

MetalLB用のnamespaceを作成するyamlがあるので使用して作成します。

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml


名前空間ができているはずなので、kubectl get nsで名前空間を確認してみます。

NAME              STATUS   AGE

----

default           Active   37d

kube-node-lease   Active   37d

kube-public       Active   37d

kube-system       Active   37d

metallb-system    Active   53s ※新しく作成された名前空間

----


MetalLBを作成します。

kubectl apply -f  https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml

kubectl apply -f configmap.yml

kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"


これでMetalLBが作成されています。

先ほど作成した名前空間「metallb-system」を指定してPodを見てみると


kubectl get pod,svc -n metallb-system

NAME                            READY   STATUS    RESTARTS   AGE

pod/controller-fb659dc8-nf5xp   1/1     Running   0          9m34s

pod/speaker-5km2t               1/1     Running   0          9m34s

pod/speaker-7gkzv               1/1     Running   0          9m34s

pod/speaker-gbx4d               1/1     Running   0          9m34s


このようにMetalLB用のPodが作成されているのがわかります。

それでは、ServiceのタイプLoadBarancerを作成して、外部アクセス用のIPアドレスが割り当てられるか見てみましよう。

前回使用したServiceを作成するのですが、確認用のPodも作成しようと思います。

今までの流れだと2個のyamlを使用していましたが、実はyamlは「---」を使用して一つにまとめることができます。

具体的には以下のような形となります。


pod.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: test-pod

  labels:

    site: test

spec:

  containers:

  - image: nginx

    name: nginx-container

---

kind: Service

apiVersion: v1

metadata:

  name: test-svc-1

  labels:

    app: test

    site: test

spec:

  type: LoadBalancer

  ports:

  - port: 80

    protocol: TCP

    targetPort: 80

  selector:

    site: test

---


ではこちらのファイルを元に作成を行ってみましょう。


kubectl apply -f pod.yaml

pod/test-pod created

service/test-svc-1 created


このように、PodとServiceが作成されていることがわかります。

MetalLBのyamlを使用して導入した際にも同じように複数のリソースを作成した出力結果

が出てきたと思いますが、あちらで使用したyamlファイルにも同様に複数のリソースを

1つのyamlにまとめていたからということです。


では、PodとServiceの状態を見てみましょう

kubectl get pod,svc

NAME           READY   STATUS    RESTARTS   AGE

pod/test-pod   1/1     Running   0          61s


NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE

service/kubernetes   ClusterIP      10.96.0.1       <none>          443/TCP        37d

service/test-svc-1   LoadBalancer   10.100.102.86   192.168.0.200   80:32383/TCP   61s


どうでしょう、作成したService「test-svc-1」にEXTERNAL-IPが割り当てられていると思います。

ここでは、tcp:80番で192.168.0.200にアクセスした場合にPodに転送されるようになっているはずです。

実際に通信可能な作業PCなどからブラウザでhttpでの通信をしてみてください。

nginxのデフォルトページが表示されると思います。


無事、ServiceタイプLoadBalancerが利用可能になりました。

これにより、IngressによるL7通信制御などもnginxのコントローラーを導入するとことで利用が

可能となり、やれることの範囲が広がっていきます。


ここで、タイトルにある時々vSphereのvSphere部分を無理やり書いてみると、vSphereのTanzuでは

この部分はNSX、HAproxy、Aviのどれかを選んで構築することになる部分となります。

VCとESXiだけではロードバランサーの役割はさすがに果たせないので仕方ない部分だと思いますが、

その分構築が複雑なのとライセンスでお金かかっちゃうのがネックですね・・・


今回は以上となります。

次回は永続ボリュームに関する『そのままだとできないこと』について書きたいと思います。

2021年10月29日金曜日

俺とkubernetesと時々vSphere -ServiceのLoadBalancerタイプ-

このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や

相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


前回までで、Kubernetesの構築、Pod、Service、永続ボリュームの利用を説明しました。

vSphereでいうところの、ESXiをインストールしてVCを構築して統合管理を行い、ストレージ

の設定してデータストアを作成し、仮想マシンを作って起動したというところですね。


基本的なことはできるようになっていますが、自分で作ったkubernetesの場合は便利な機能が

使えない状態になっています。


例えば、ServiceにはLoadBalancerというタイプのものがあります。

これを作成してみましょう。

以下のyamlを用意し、kubectl apply -f を実行します。

---

kind: Service

apiVersion: v1

metadata:

  name: test-svc-1

  labels:

    app: test

    site: test

spec:

  type: LoadBalancer

  ports:

  - port: 80

    protocol: TCP

    targetPort: 80

  selector:

    site: test

---


無事作成できたように見えますが、状態を見てみると以下の様にいつまでもEXTERNAL-IPが<pending>のままです。


kubectl get svc

NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP        27h

test-svc-1   LoadBalancer   10.107.138.238   <pending>     80:31352/TCP   7s


当然外部からアクセスするIPアドレスがないので通信ができません。

このように、手動作成のKubernetesには一部機能が備わっていなくてそのままだと使えないものがあるという状態です。


今回例として挙げた、ServiceのLoadBalancerタイプですが、以下の様な動作でユーザーからのアクセスをさばいてくれます。

                                    

<ユーザー>

  →<Service:LoadBalancer>

   →<Kubernetesクラスタノードのどれか>

    →<Serviceと紐ついているPodのどれか>


つまり、ユーザーとKubernetesクラスタの間にLoadBalancerが入って、ユーザーからのアクセスをNodePortdで待ち構えるKubernetesクラスタのノードどれかに渡します。

ユーザーはLoadBalancerのIPにアクセスすればいいわけですから、KubernetesクラスタのノードのIPアドレスが変わっても特に意識することがなくなります。


勘のいい方は、えっそれって・・・と思われたかもしれません。

そうです。Kubernetesクラスタの外部にLB立ってます。

なので、手動で構築したままのKubernetesクラスタでServiceのLoadBalancerを作成しても、連携してくれるLoadBalancerがいないので、EXTERNAL-IPが<pending>のままになってしまうのです。

しかし、それをどうにかやってくれるありがたい存在があります。

その名をMetalLB、来月はこのMetalLBをどのように導入してどのように使うのかについて解説したいと思います。


ちなみに、マネージドkubernetes(GCPやAWS等で提供されているKubernetes)は、ServiceのLoadBalancerが作成されると連携してLoadBalancerが展開されます。

この辺の管理も含めて便利になっているのがサービスとして提供されているKuberneteのいいところですね。

2021年9月30日木曜日

俺とkubernetesと時々vSphere -PodとServiceの作り方-

このブログは、コンテナのオーケストレーターであるkubernetesについて自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


今回は前回からの続きで、Podにストレージを追加するための作業をやっていきたいと思います。

今回はちょっと登場人物が多かったり、作業を行うための準備が必要だったりで少し難しいと思います。

文章だけだと難しいと思いますので、読み飛ばして実際にyamlから物を作成してもらったほうが早いかもしれません。


Podのストレージを永続ストレージと呼び、具体的にKubernetesではそれのことをPersistentVolumeと呼びます。

仮想マシンに置き換えると、仮想ディスクに当たる部分になります。

Pod同様PersistentVolumeもyamlで作るのですが、PersistentVolume(PV)を作っていい領域がどこかそれが定義されていないと作れません。

何のことかちょっとよくわからないかもしれませんが、vSphere的に言うと仮想ディスクを作成するためのデータストアを用意しないといけないという感じです。

では、そのデータストアをどう作るかというと、StorageClass(SC)というリソースを作成してKubernetesに「この領域が使えますよ」と定義するわけです。

これで、SCで定義された領域にPVを作ることができました。

しかし、この状態は、仮想ディスクはできたけど仮想ディスクを使うのは誰かという部分が設定されていません。

その設定を行えるようにするのがPersistentVolumeClaim(PVC)です。

PVCはPVを要求するためのリソースで、どんなサイズのPVが欲しいかという内容が定義されています。

このPVCをPodのyamlに書いてあげると、PVCに要求されたサイズのPVがPodと紐づくことができます。

これは文章で読んでもあんまり理解できないと思いますので、気にせず実際に作ってみましょう。


まずはStorageClassから。

ここでは、NFSやiSCSIなどの外部ストレージ装置ではなく、ローカル領域を指定します。

以下の内容をKubernetesクラスターにvi等で作成してください。


  local-sc.yaml

  ----

  kind: StorageClass

  apiVersion: storage.k8s.io/v1

  metadata:

    name: local-sc

  provisioner: kubernetes.io/no-provisioner

  ----


続いて、作成したStorageClassであるlocal-scを指定してPersistentVolumeを作成。

以下の内容をKubernetesクラスターにvi等で作成してください。


  local-pv.yaml

  ----

  apiVersion: v1

  kind: PersistentVolume

  metadata:

    name: local-pv

  spec:

    capacity:

      storage: 3Gi

    volumeMode: Filesystem

    accessModes:

      - ReadWriteOnce

    persistentVolumeReclaimPolicy: Delete

    storageClassName: local-sc

    hostPath:

      path: /local-pv/

  ----


さらに、用意したPersistentVolumeを要求するPersistentVolumeClaimを作成します。

以下の内容をKubernetesクラスターにvi等で作成してください。


  local-pvc.yaml

  ----

  apiVersion: v1

  kind: PersistentVolumeClaim

  metadata:

    name: local-pvc

  spec:

    accessModes:

    - ReadWriteOnce

    volumeMode: Filesystem

    resources:

      requests:

        storage: 3Gi

    storageClassName: local-sc

  ----


それでは順番に、作成を行いましょう


  kubectl apply -f local-sc.yaml

  kubectl apply -f local-pv.yaml

  kubectl apply -f local-pvc.yaml


確認は以下のコマンドで


  kubectl get sc,pv,pvc


出力結果はこんな感じ


  NAME                                                   PROVISIONER                                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE

  storageclass.storage.k8s.io/local-storage              kubernetes.io/no-provisioner                    Delete          Immediate           false                  82s 

  

  NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE

  persistentvolume/local-pv                                   3Gi        RWO            Delete           Bound    default/local-pvc        local-sc                18s

  

  NAME                                   STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS               AGE

  persistentvolumeclaim/local-pvc        Bound     local-pv                                   3Gi        RWO            local-sc                   3s


と、ここまでで仮想マシンで言うと仮想ディスクができたわけです。

しかしこのままでは、この仮想ディスクを使う仮想マシンが誰かという設定がされていません。

そこでもう一つyamlが必要となります。


どんなyamlが必要となるかというと、Podのyamlです。

Podのymalにこのpvcを組み込むことで、PodがようやくPVCを使えるようになります。

前回作ったnginxのPodにくっ付けて新しいPodのyamlファイルを作ってみましょう


  nginx-pv.yaml

  ----

  kind: Pod

  apiVersion: v1

  metadata:

    name: nginx-pod-2

    labels:

      app: wcp-demo

  spec:

    containers:

    - image: nginx

      name: nginx-container

      volumeMounts:

      - name: nginx-pv

        mountPath: /pv

    volumes:

    - name: nginx-pv

      persistentVolumeClaim: 

        claimName: local-pvc

  ----


これを作成するとPodが付いています。


  kubectl apply -f nginx-pv.yaml


しかし、実際にPVはどこにできているかというと、Podが動いているnodeの/local-pv/になります。

確認するには"kubectl get pod -o wide"を実行するとわかります。


Podにくっ付けられたPVは本当にくっついているか確認します。

Podの内部に入って/pvディレクトリがあるか確認しましょう。


  kubectl exec -i -t pod/nginx-pod-2 /bin/bash


  cd /pv


ディレクトリ/pvに移動することができました。

ダミーファイルを作成してみましょう。


  dd if=/dev/zero of=2G.dummy bs=1M count=2048


ファイルができたら、exitでPodから抜けます。

Podが動作しているノードへログインして、/local-pv/にファイルがあることを確認してください。


では、以下のコマンドでPodを削除してみましょう。


  kubectl delete -f nginx-pv.yaml


PVをくっ付けていないPodの場合、先ほど作成したダミーファイルも一緒に消えます。

もう一度同じyamlでPodを作成しなおしてみましょう。


  kubectl apply -f nginx-pv.yaml


Podにログインしてlsで/pvを確認するとダミーファイルが残っていることが確認できるはずです。


今回はここまでとなります。

2021年8月31日火曜日

俺とkubernetesと時々vSphere -作ってみよう、PodとService-

このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。


今回は前回説明した、Pod、Service、Podへ外部ストレージ領域の追加を実際にどうやったらいいのかという説明をしたいと思います。

まずはPodとServiceについて解説します。


Kubernetesクラスタ内部で何かを作成するとき、コマンドラインでの作成も一応できるのですが基本はymalファイルというものを使います。

yamlファイルとはなにかというと、これから作りたいものの設計図です。


yamlには大きく分けて4つのセクションがあり、それぞれ以下のような役割を持ちます。


  apiVersion:リソース作成時に使用するAPIのバージョンの設定

  kind:どの種類のリソース(Pod、Service等)を作成するかの設定

  metadata:リソースを一意にするための設定(名前、namespace、UID等が該当)

  spec:リソースの状態を設定(Podなら開放するportやCPU、メモリのサイズ等)


実際のPod、Serviceのyamlの例を見てみましょう。

Pod用ymalファイルの例

==========

---

kind: Pod

apiVersion: v1

metadata:

  name: nginx-pod

  labels:

    app: wcp-demo

spec:

  containers:

  - image: nginx

    name: nginx-container

==========

Kind → Podを作成するのでPodを記載

apiVersion → Podが所属しているAPIがv1であるため、v1を記載

metadata → nameには一意となる名前を設定、labelsにはPodに付与するラベル(app: wcp-demo)を設定

spec → containersはコンテナに関する設定を行うフィールド

        imageで作成するコンテナのイメージを指定、nameにはコンテナの名前を設定


Service用ymalファイルの例

==========

---

kind: Service

apiVersion: v1

metadata:

  name: nginx-svc

spec:

  type: NodePort

  ports:

  - port: 80

    protocol: TCP

    targetPort: 80

  selector:

    app: wcp-demo


Kind → Serviceを作成するのでServiceを記載

apiVersion → Serviceが所属しているAPIがv1であるため、v1を記載

metadata → nameには一意となる名前を設定

spec → typeで作成するServiceのタイプを設定

           ※ここでは、クラスタのノード全てでアクセスを受け取れるNodePortを指定

        portsはポートに関する設定を行うフィールド

        portはportからtargetPortへのマッピングを行います。利便性のため基本的にはtargetPortと同じ値を入れます。

        protocolは使用する通信のプロトコルを指定

        targetPortはコンテナに転送するportを指定

        selectorは一致するラベルを持ったPodを探し転送先として認識します。

==========


このようなyamlを用意するわけですが、どのようにこのファイルからPodやServiceを作成するのかというと

以下のコマンドを使用します。


  kubectl apply -f <yamlファイルまでのパス>


ここではAdministratorのデスクトップに配置したyamlを使用して実行した例を紹介します。


■Podの作成

  PS C:\Users\Administrator> kubectl apply -f "C:\Users\Administrator\Desktop\nginx-pod.yml"

  pod/nginx-pod created


■Serviceの作成

  PS C:\Users\Administrator> kubectl apply -f "C:\Users\Administrator\Desktop\nginx-pod-svc.yml"

  service/nginx-svc created


作成したPodとServiceはkubectl get <確認したいリソース> で確認可能です。

複数のリソースを確認したい場合は、「,」で区切ります。


■Podの確認

  kubectl get pod

  NAME        READY   STATUS    RESTARTS   AGE

  nginx-pod   1/1     Running   0          14m


■Serviceの確認

  kubectl get service

  NAME        TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE

  service/nginx-svc    NodePort    10.108.236.173   <none>        80:32074/TCP   4s


■PodとService両方確認

  kubectl get pod,svc

  NAME            READY   STATUS    RESTARTS   AGE

  nginx-pod       1/1     Running   0          14m


  NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE

  service/nginx-svc    NodePort    10.108.236.173   <none>          80:32074/TCP   4s


ここで、Serviceの PORT(S) に表示されている80:32074が<Podへ転送するport>:<ユーザーがアクセスするport>

となります。

<ユーザーがアクセスするport>は自動で付与されるため環境によって異なります。


ServiceのタイプがNodePortというKubernetesクラスタを構成しているノードの、どのIPアドレスどれでも

アクセス可能なServiceとなっているため、どれか一台のIPアドレスに<ユーザーがアクセスするport>を

くっつけてブラウザからhttpでアクセスしてみましょう。


  例

   http://192.168.0.100:32074


nginxのページが確認できたと思います。


今回はここまでとなります。

次回は、このpodを削除してもデータが残せるよう永続ボリュームをくっつくけるための内容を説明したいと思います。


2021年7月30日金曜日

俺とkubernetesと時々vSphere ーKubernetesで扱うことになるPod、Service、StrageClassやPersistentVolume、PersistentVolumeClaimってなんでしょう?ー

このブログは、コンテナのオーケストレーターであるkubernetesについて

自分の知識をまとめることを目的として記事を書いています。

もともとなが~くvSphereのあれやこれやに携わってきたのでvSphereとの類似点や相違点についてもちょっと混ぜていけたりしたらいいかなぁとかも思っています。

今回は前回構築したkubernetesクラスターに構築するPod(コンテナ)、Service(Podのネットワーク)、

Podのストレージ(Strageclass、PersistentVolume、PersistentVolumeClaim)についての説明をしたいと思います。


1.Pod

 Podは実際にアプリケーションが動作する場所(vSphereで言うと仮想マシン)となりますが、Kubernetes上で動くコンテナといったところです。

 Pod中には複数のコンテナを展開することもできますが、基本系は1Pod1コンテナですので、最初はPod=コンテナと思っても大丈夫だと思います。

  Pod単体でアプリケーションを起動することはできますが、外部との通信はできません。

 また、Pod内部にデータが保存されている場合Podを停止(Kubernetesの世界ではPodの停止=Podの削除)すると保存していたデータも一緒に消えてしまいます。

 その問題点を解消するのが以下の2つになります。


2.Service

 ServiceはPodとPodを接続したり、Podと外部の接続を行うPod用のネットワークです。

 Kubernetes内部でのみ使用する場合(外部とのやり取りが発生しない)や外部と通信する場合等の用途に合わせてタイプを指定することができますが、外部と通信を行う場合はどのように外部との中継を行うか種類が選べます。


   内部通信用のService

    ClusterIP


  外部通信用のService

   ExternalIP →任意のマスターorワーカーを指定して外部からPodへ通信を行う

   NodePort →Kubernetesクラスタ内のノードどれにアクセスしても外部からPodへ通信が可能

   Loadbarancer →外部ロードバランサが利用できるクラウドプロバイダ用ですが、ロードバランサーを自動で作成して連携してくれます。※そのため自分で作成したKubernetesクラスタだとそのままでは使えません。


3.Podのストレージ

 Pod内の動作によって出力されたデータなどを保存しておきたい場合、Pod外部にデータを保存する必要があり、具体的には以下の作業が必要です。


     Podで使えるストレージを定義(vSphereで言うとデータストアに近い)

   →定義されたストレージにPod用の領域を作成(vSphereで言うと仮想ディスクに近い)

    →Pod用のの領域をPodに紐付ける(しいて言えば、仮想マシンの設定と編集でディスクを手動追加するイメージ)


 この作業はKubernetes的な言い方をすると以下の様になります。


   StrageClass(SC)を作成する。

    →PersistentVolume(PV)を作成する。

    →PersistentVolumeClaim(PVC)を作成する。


これらをくっ付けて、Pod内のアプリケーションへ外部からアクセスしたり行わせた処理を保存したりできるようになるのですが、PodもServiceも作成しただけでは、お互いに紐ついてくれません。

これらをくっ付けるために必要なラベルとラベルセレクターという存在があります。

また、ストレージもそのままでPodと紐ついてくれません。

こちらも、yamlというPodやServiceを作る際に使用する設計書の様なものを利用する必要があります。


というわけで、次回はこれらの作り方やお互いが利用しあえるための設定、yamlの書き方について説明したいと思います。