[注意] !!!sks-keyservers.net は終了しているのでこの設定は意味がありません!!! [追記]
続きを読むGoBGP で経路フィルタを書く
ボーと眺めていたら必要ない経路を広報していたのでフィルタ書くかーと思ったので、メモておく。
続きを読むGoBGP で受け取った経路を Quagga (zebra) でカーネル経路に落とし込む
vagrant で k8s クラスタを作った記録では以下のように書いていました。
gobgpd と quagga を使った BGP ルータの構築も https://github.com/nabeo/vagrant-k8s-metallb で構築していますが、ここでは詳しくは触れません。
ということで、今回は gobgpd で受けた BGP 経路を Quagga で kernel の経路表に落とし込んで別サブネットに存在しているクライアントが k8 で構築しているサービスにアクセスできるようにしている部分の解説をしようと思います。Quagga でも BGP を受けれることは承知していますが、GoBGP を使ってみたかったのでこんな構成にしています。
続きを読むk8s クラスタを気軽に遊べる環境を作っている
k8s のマネージドサービスとして GKE や EKS などで出揃った感はあるけど、マネージドサービスでは k8s クラスタの全ての機能を使うことはできないという認識です。特にネットワークなどインフラよりな低レイヤーな部分はマネージドサービス側でいい感じに隠蔽して、利用者は意識する機会は少ないです。最近は仕事でも k8s など docker コンテナ基盤を扱う機会が増えてきていますが、インフラ屋さんとしてはこのような低レイヤーな部分が気になることがあるので、k8s クラスタを手軽に作れる環境が欲しくなりました。
というわけで、Vagrant を使って手元の仮想環境の管理をしつつ、ansible で k8s クラスタの構築する環境を作りました。ただし、ansible で k8s クラスタを構築する、といっても ansible で完結しておらず、一手間が必要です。というわけで、以下のレポジトリ でどのように k8s クラスタを作っているかを解説してみます。
構築する k8s クラスタ環境
レポジトリの README.md にありますが、構築する環境は以下のようなネットワークになっています。
client (172.17.1.0/24 / ASN 64512) -------+--------------+------------ | | eth1|.1 enp0s8|.10 +----+----+ +-----+-----+ | rt-01 | | client-01 | +----+----+ +-----------+ eth2|.1 | k8s-cluster (172.17.0.0/24 / ASN 64522) -------+-----+------------------+-----------------+-----------------+-------- | | | | enp0s8|.10 enp0s8|.21 enp0s8|.22 enp0s8|.23 +-------+-------+ +------+------+ +------+------+ +------+------+ | k8s-master-01 | | k8s-node-01 | | k8s-node-02 | | k8s-node-03 | +---------------+ +-------------+ +-------------+ +-------------+
レポジトリ名から予想がつきますが、k8s の LoadBalancer として metallb を使うため、BGP ルーター(rt-01
) も構築しています。また、metallb で使用する AS 番号として 64522 を定義しています。また、k8s の CNI プラグインとして flannel を採用しています。各ネットワークのアドレスブロックは以下のようにしています。
- docker0 : 172.17.255.0/24
- k8s
- Flannel Pod Network CIDR : 10.244.0.0/16
- Service CIDR : 10.244.0.0/16
- BGP network : 172.17.254.0/24
- ASNs
- client 64512
- k8s-cluster 64522
また、k8s クラスタの管理には kubeadm
を全面的に採用しています。
k8s クラスタの構築
k8s 環境の構築
https://github.com/nabeo/vagrant-k8s-metallb を git clone
してきたディレクトリで make up
を実行します。内部的には各 VM 定義に対して vagrant up
が実行され、Vagrant の ansible_local
によるプロビジョニングが実施されます。ansible_local
のプロビジョニングでは以下を実施していないため、後の手順で手動で実施する必要があります。
k8s-node の k8s クラスタへの参加と worker ノードとしての登録
まず、make k8s-master-01-ssh
で k8s-master-01
ノードに ssh ログインします。
k8s-master-01
で kubeadm token create --print-join-command
を実行して、worker ノードが k8s クラスタに参加するためのトークン発行と k8s クラスタに参加する worker ノードで実行するべき kubeadm join
コマンドを表示させます。
次に、各 worker ノードで k8s-master-01
ノードで取得した kubeadm join
コマンドを実行して、k8s クラスタに参加させます。
この時点では worker ノードは k8s クラスタに参加していますが、worker ノードとしては認識されていないので、k8s-master-01
で以下を実行して worker ノードとして登録します。
kubectl label nodes <hostname> node-role.kubernetes.io/node= kubectl label nodes <hostname> type=worker
全ての worker ノードの準備が整ったら、 kubectl get nodes
では以下のように表示されていると思います。
NAME STATUS ROLES AGE VERSION k8s-master-01 Ready master 42d v1.15.1 k8s-node-01 Ready node 42d v1.15.1 k8s-node-02 Ready node 5d18h v1.15.1 k8s-node-03 Ready node 5d18h v1.15.1
metallb の構築
Vagrantfile では vm との synced_folder
として ansible プレイブックを配置している ansible
ディレクトリの他に雑多なファイルを格納するための shared
ディレクトリを登録しています。k8s クラスタで使用するマニフェストファイルも shared
ディレクトリに配置しています。
ということで k8s-master-01
で shared/k8s-configs
にある以下のファイルを kubectl apply
で読み込ませます。
metallb.yaml
metallb-bgp.yaml
metallb.yaml
は metallb の v0.7.3 をベースにして、Vagrant 環境で使えるように調整しています。metallb-bgp.yaml
は metallb を BGP モードで使用し、rt-01
に BGP ピアを貼るようにしています。
metallb は k8s クラスタの metallb-system
という名前空間を使用しています。1つの controller pod と worker ノード数分の speaker pod が立ち上がっているはずです。
k8s クラスタで遊ぶ
試しに nginx をデプロイしてみます。以下のマニフェストを kubectl apply
で読み込ませます
--- apiVersion: apps/v1beta2 kind: Deployment metadata: name: nginx-deployment spec: replicas: 6 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx-container image: nginx:alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - name: http port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
ここでは nginx
サービスの type
を LoadBalancer
とすることで metallb を使うようにしています。kubectl apply
によって環境がデプロイされると、rt-01
では以下のように nginx
サービスの EXTERNAL-IP である 172.17.254.1 の next hop が worker ノードに向いているような経路が BGP で広報されたことがわかります。
vagrant@rt-01:~$ gobgp monitor adj-in 2019-07-27T07:32:17Z [ROUTE] 172.17.254.1/32 via 172.17.0.23 aspath [64522] attrs [{Origin: ?}] 2019-07-27T07:32:17Z [ROUTE] 172.17.254.1/32 via 172.17.0.21 aspath [64522] attrs [{Origin: ?}] 2019-07-27T07:32:17Z [ROUTE] 172.17.254.1/32 via 172.17.0.22 aspath [64522] attrs [{Origin: ?}]
また、rt-01
では gobgpd
で受け取った経路を quagga
の zebra
でカーネル経路に落とし込んでいるので以下のように ip route
でも確認できます。
172.17.254.1 proto zebra metric 20 nexthop via 172.17.0.22 dev enp0s8 weight 1 nexthop via 172.17.0.21 dev enp0s8 weight 1 nexthop via 172.17.0.23 dev enp0s8 weight 1
gobgpd
と quagga
を使った BGP ルータの構築も https://github.com/nabeo/vagrant-k8s-metallb で構築していますが、ここでは詳しくは触れません。
k8s クラスタを kubeadm でアップグレードしたときのメモ
最近は手元で k8s クラスタを作って遊んでいます。いつの間にか k8s の 1.15 系が使えるようになっていたので、kubeadm を使ってクラスタのアップグレードをしてみました。
手順は以下の kubeadm を使った 1.14 から 1.15 へのアップグレード手順をなぞっただけです。
実際に実施した時の手順のメモは以下。
特に複雑なことはしていないクラスタだったので、すんなりアップグレードできてしまった。
ただ、アップグレードが終わった後に kubectl get all
とかしていると特定の worker node に割り当たっている coredns の Pod が起動失敗している気配があったので、kubeadm を使って該当 worker node をクラスタから離脱させて再参加させるようなことをしていました。
最近は Vagrant では ansible_local でプロビジョニングしている
vagrant で手元の VirtualBox に検証環境を作る場合は Ansible Local Provisioner を使っています。
昔は Ansible Provisioner を使っていたけど、手元環境を汚さずに仮想ホスト上で ansible を直接実行できることにメリットを感じています。
Vagrantfile はこんな感じで準備しておきます
Vagrant.configure(2) do |config| config.vm.synced_folder './ansible', '/home/vagrant/ansible', create: true, owner: 'vagrant', group: 'vagrant' config.vm.define 'vm01' do |node| node.vm.provider 'virtualbox' do |vb| vb.cpus = 1 vb.memory = 512 vb.gui = false end node.vm.hostname = 'vm01' node.vm.box = 'ubuntu/cosmic64' node.vm.provision :ansible_local do |ansible| ansible.compatibility_mode = '2.0' ansible.playbook = '/home/vagrant/ansible/all.yml' ansible.inventory_path = '/home/vagrant/ansible/inventories/hosts' ansible.limit = 'clients' end end
Vagrantfile
があるディクトリに ansible
ディレクトリを作って、その下に ansible playbook を配置しています。で、asible
ディレクトリは config.vm.synced_folder './ansible', '/home/vagrant/ansible'
で VM 上の /home/vagrant/ansible
として配置しています。
Ansible Local Provisioner を使うときの注意点としては ansible は vm 上で動くため、inventory file は自分自身をプロビジョニング対象にする必要があります。vagrant-hosts プラグインなどを使って hosts ファイルを管理してもいいのですが、僕は inventory file を ansible の role ごとに分けて管理しています。したがって、 ansible
ディレクトリの中身はこんな感じになっています
ansible ├── all.yml <--- ansible.playbook で指定している ├── clients.yml | ├── inventories │ └── clients <--- ansible.inventory_path で指定している | └── roles ├── clients └── role_template
また、inventory file は ansible をローカル環境を対象に実行する必要があるので、以下のように書いています。
[clients] 127.0.0.1 ansible_connection=local
未来大×企業エンジニア 春の LT 大会で LT してきました #springlt_hakodate
未来大×企業エンジニア 春のLT大会に登壇させてもらえる機会があったので、函館の元気な若者に会いに行ってきました。
お題は「これだけは伝えておきたい技術」ということで、若者に刺さって10分の発表枠に収まりそうな内容ということで、かなり悩みました。そんな悩みを抱えていたある日、社内の若者と雑談していると Docker イメージを小さくするテクニックだと手軽に話せて、かつ、若者に刺さりそう!!ということに気づいたので、こんな資料を作って LT してきました。
大きな講義室にびっしりと聴講者が入ってとても大盛況なかで、「なるほど、最近の学生さんてこういうことに興味あるのか」と発見させられたりととても有意義なイベントでした。また、LT 大会後の懇親会では、自分の学生時代にこんなイベントがあったらもう少し違った学生生活してたかもなーと思いながら話を聞いていました。イベント運営スタッフの皆さん、お疲れ様でした、とても楽しいイベントでした。
また、Tiwtter のタイムラインで指摘されている方もいましたが、DockerCon19 で Dockerfile Best Practices というセッションでイメージサイズの圧縮とは異なる切り口でも触れられているのでより深く知りたい方はオススメです。
あと、スライドの最後にも告知していますが、はてなサマーインターン 2019 の募集が始まっています。興味のある方は応募してください!待ってます!!!