LoginSignup
10
10

More than 3 years have passed since last update.

ネットワークまわりを確認&勉強しながら、Kubernetesの環境構築をしてみた

Last updated at Posted at 2020-08-01

はじめに

構成概要

構成図

  • 今回構築した環境は下記の通りです。
  • AWSでEC2を3台立てて検証しました。

k8s_nw_3.png

補足

  • EC2を配置しているVPCにはIGWを関連付けている
  • EC2を配置しているVPCのIPレンジとして10.1.100.0/16を設定している
  • flannelのIPレンジは、デフォルトのbridege(172.17.0.0/16など)と被らないよう設定する必要がある
    • 今回は、172.21.0.0/16を指定した
  • ホストに複数のNICが接続されている場合は、他のクラスタノードと通信するNICを、 kubeadm init --apiserver-advertise-address で指定する(今回は1枚)
  • 起動したPodに対して、ユーザ(インターネット経由)は http://18.176.61.21:30000 などでアクセスできる

構築手順

[Ctrl/Node] EC2作成

  • 2CPU/メモリ2GB以上でOSが対応していれば良さそう
* セキュリティグループ作成
    * ローカルPCからのssh
    * 下記インスタンス間のtcp(プライベートIP)
* インスタンス作成
    * Ubuntu Server 18.04 LTS
    * t2.medium

k8s_nw_1.png

[Ctrl/Node] Dockerをインストール

# 必要なライブラリを事前にインストール
$ sudo apt update
$ sudo apt install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# GPG公開鍵のインストール
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 公開鍵のフィンガープリントを確認
$ sudo apt-key fingerprint 0EBFCD88
# aptリポジトリの設定
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# dockerインストール
$ sudo apt update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# 動作確認
$ sudo docker run --rm hello-world
$ sudo docker rmi hello-world

k8s_nw_2.png

[Ctrl/Node] kubeadmをインストール

# GPG公開鍵のインストール
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
# aptリポジトリの設定(Googleが提供しているパッケージリポジトリを登録)
$ sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"

# kubeadmインストール
$ sudo apt update
$ sudo apt install -y kubeadm

# swapをオフにする
#   これだとOS再起動の度に必要になるので、/etc/fstabファイルを編集するのがよい
$ sudo swapoff -a

[Ctrl] Kubernetesをセットアップ

# コントロールプレーンのセットアップ
#   etcd、apiserver、controller-manager、schedulerといったコンテナを起動するなど、色々
#   --apiserver-advertise-address: 他ノードと接続できるネットワークインターフェイスに割り当てられているIPアドレスを指定する
#   --pod-network-cidr: KubernetesのPod(コンテナ)に割り当てるIPアドレス範囲
#   上手くいかなかった場合、 kubeadm reset を実行して設定をリセットしてから再度実行する
$ sudo kubeadm init --apiserver-advertise-address=10.1.100.11 --pod-network-cidr=172.21.0.0/16

# kubectlコマンド設定ファイルの配置
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
# ノード確認
#   ネットワーク関連の設定が完了していないため、STATUSはNotReadyでよい
$ kubectl get nodes

# flannelのセットアップ
#   コンテナ間の通信を行うための仮想ネットワーク

# flannelのためにiptablesを編集
$ sudo sysctl net.bridge.bridge-nf-call-iptables=1
# 設定ファイルの取得、修正
$ wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# net-conf.json: 以下の ”Network” の値を、kubeadm initコマンド実行時に --pod-network-cidr オプションで指定したものに変更する
$ vim kube-flannel.yml
---
"Network": "172.21.0.0/16",
---

# flannelの作成
$ kubectl apply -f kube-flannel.yml

# ノード確認
$ kubectl get nodes

# (参考)クラスタを作り直す場合、上記で作成した仮想インターフェイスを一旦削除しておく
# ip link delete cni0, ip link delete flannel.1

[Node] クラスタにjoinする

# クラスタにjoinする
$ sudo kubeadm join 10.1.100.11:6443 --token xxxxxx.xxxxxxxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxx

# ノード確認(コントロールプレーンにて実行)
$ kubectl get nodes

[Ctrl]JupyterNotebookコンテナを作成・接続

  • マニュフェストファイル作成 -> 実行
    • コマンドだと、 docker run -p 10000:8888 --name jupyter docker.io/jupyter/scipy-notebook
notebook.yaml
# Deployment
#   アプリケーションの配布単位を管理するリソース
#   ReplicaSetを管理する(ReplicaSetの履歴を持つ)
#   ReplicaSet: 指定された数のPodを複製し、実行してくれる
apiVersion: apps/v1 # APIのバージョン情報
kind: Deployment # リソースの種類
metadata:
  name: test-notebook # リソースの名前

spec: # リソースの詳細
  selector: # ここで指定したPodを起動する
    matchLabels:
      app: notebook # Podのテンプレートを指定する([A])
  replicas: 1 # クラスタ内で起動するPodの数

  template: # 作成される(動かしたい)Podのテンプレート
    metadata:
      labels:
        app: notebook # PodにLabelを付ける([A]と対応)
    spec:
      containers:
      - name: notebook # コンテナ名
        image: docker.io/jupyter/scipy-notebook # コンテナイメージの場所
        ports:
        - containerPort: 8888 # ポート番号

---
# Service
#   クラスタ内のPodに対して、クラスタ内部および外部のネットワークからアクセスするためのリソース
#   Selectorで選択したPodをUpstreamとしたLB
apiVersion: v1 # APIのバージョン情報
kind: Service # リソースの種類
metadata:
  name: test-service # リソースの名前

spec: # リソースの詳細
  type: NodePort # [ClusterIP, NodePort, LoadBalancer, ExternalName]
  selector: # ここで指定したLabelが付与されているPodに伝送する
    app: notebook # ([A]と対応)
  ports:
    - port: 8888 # ポート番号
# Podのデプロイ
$ kubectl create -f notebook.yaml
# ポート確認
$ kubectl get svc
# logを見てtoken確認
$ kubectl get pod
$ kubectl logs XXX
# -> http://:<30000台のポート>/ でアクセス可能

k8s_nw_3.png

メモ

確認に使ったコマンド

  • NW
# IP確認
$ ip addr show

# NIC確認
$ ifconfig

# iptables確認
$ sudo iptables -nL

# ルートテーブル確認
$ route
  • Kubernetes
# クラスタ確認
$ kubectl cluster-info

# ノード確認
$ kubectl get nodes
$ kubectl get nodes -o==wide
$ kubectl describe node XXX

# ポッド確認
$ kubectl get pod
$ kubectl get pod -o wide
$ kubectl get pod --show-labels
$ kubectl get pod -l env=prod
$ kubectl describe pod XXX
$ kubectl logs XXX

# サービス確認
$ kubectl get svc

# まとめて確認(Deployment, ReplicaSet, Pod, Service)
$ kubectl get all

ネットワークについて

  • AWS

    • グローバルIPがOSから(ifconfigで)見えない
      • グローバルIPは、コンソールのネットワークインターフェイスのプロパティとして表示されるが、実態はNATによってプライベートIPにマッピングされている。
  • Docker

    • コンテナとして起動するサービスを外部に公開する場合は、コンテナホストの特定ポートに対するアクセスをコンテナに対してiptablesによりDNATすることで、コンテナに対するアクセスを実現している。
  • Kubernetes

    • flannel
      • Docker単体での利用との違いは、ノードを跨ぐこと。各Podにはノードごとに独立したIPアドレスが割り当てられるが、ノード跨ぎの場合は課題が発生する。Docker単体ではNATを利用しているが、Pod作成の度にNATテーブルを操作するのは効率的ではないため、オーバーレイネットワークを採用している。
      • 詳細はわかった気になるflannelの仕組みが分かりやすい

参考リンク

10
10
0

Register as a new user and use Qiita more conveniently

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