既定のアプリをコマンドで変更する方法
Windows 10の10月24日のアップデートでGUI上から一部の既定のアプリを変更することができないようになっているみたいです。これに見事にはまり、.txt
ファイルの既定のアプリをメモ帳から変更できなくなってしまいました。。。
Microsoft側もこのことを認識しており、11月下旬に向けて修正を予定しているようです。 https://support.microsoft.com/en-us/help/4462933/windows-10-update-kb4462933
Symptom | Workaround |
---|---|
After installing this update, some users cannot set Win32 program defaults for certain app and file type combinations using the Open with… command or Settings > Apps > Default apps. In some cases, Microsoft Notepad or other Win32 programs cannot be set as the default. | In some cases, attempting to set application defaults again will succeed. Microsoft is working on a resolution and estimates a solution will be available in late November 2018. |
11月下旬まで待ってられるか!という人は以下のようにして変更できるみたいです。
ftype txtfile="<テキストエディタのパス>" "%1"
OpenStackとoVirtで自宅クラウド環境を構築してみた
お久しぶりです。4か月間ぐらい全くポストしていませんでしたが生きています。
何やっていたかというと、自宅環境をOpenStackによってプライベートクラウド化しておりました。これが完成しないと諸々の検証ができないので、ブログのポストより優先していたら4か月も経っていた感じです。
4か月間にためていたナレッジは少しずつ文章にしていくつもりですが、まずはどんなプライベートクラウド環境を構築していたのか紹介する記事を書こうと思います。自宅環境を構築したい人、している人の少しでも参考になれば幸いです。
目的
本プライベートクラウド環境の目的ですが、以下の通りです。
- 製品の検証(主にインフラの検証。ハイパバイザレベルでの検証も含む)
- サービス提供(Wikiサイトなど)
従来はoVirtというOSSの仮想化基盤製品でこれらの目的をこなしていたわけですが、プライベートクラウド化することによって次のことを狙っていました。
- 様々なサービスのAPIコールによるデプロイ
oVirtはあくまで仮想化基盤なので、あくまでもAmazon EC2やEBS相当の機能しか提供してくれません。昨今のクラウドネイティブなアーキテクチャの学習には不向きだったのです。またコンテナ中核技術であるKubernetesの利便性を最大限引き出すにはクラウドとの連携は必須となります。このためOpenStackによって自宅IaaSを構築しようという考えに至りました。
ただし、OpenStackでは柔軟な仮想マシン設定を行うことが難しくなり、KVMなどのハイパバイザレベルでの動作検証が難しくなります。したがって検証環境すべてをOpenStackに移行したわけではなく、一部リソースをoVirt用に残すようにしました。
アーキテクチャ(物理)
物理構成は以下の通りになります。OpenStack Controllerはロードバランサなどの補助サーバはoVirt上のVMとして構築します。
- Intel NUC Pentiumモデル x 1 (oVirt Engine用)
- Intel NUC Corei3モデル x 3 (oVirt Node用)
- Intel NUC Corei3モデル x 3 (OpenStack Compute用)
アーキテクチャ(仮想)
VMを含めた構成は以下の通りです。冗長化による性能向上を狙って、OpenStack環境はActive/Activeクラスタを構成しています。(Cinder Volumeを除く)
構築したサービス
本プライベートクラウドでは以下のIaaSサービスを提供しています。
oVirt
通常の仮想化環境を提供します。KVM等のハイパバイザ自体を検証したいときはこっちを使います。VMやボリュームのプロビジョニングを行うことができ、通常の仮想化環境といってもAPIがついているので、Ansible等を用いてプロビジョニングを自動化することが可能です。OpenStack Keystone
AWSにおけるIAM相当の認証基盤を提供します。OpenStack Swift
AWSにおけるS3相当のオブジェクトストレージ機能を提供します。OpenStack Glance
AWSにおけるAMI相当のVMイメージストア機能を提供します。Swiftと連携してイメージをSwiftに保存するようにしています。OpenStack Neutron
AWSにおけるVPC、ELB相当の仮想ネットワーク、ソフトウェアロードバランサー機能を提供します。OpenStack Heat
AWSにおけるCloudFormation相当のオーケストレーション機能を提供します。OpenStack Magnum
AWSにおけるECS、EKS相当のコンテナオーケストレーション機能を提供します。Kubernetesのデプロイを一発で行えます。
まとめ
OSSを使って自宅環境をプライベートクラウド化してみましたが、ソフトウェアでインフラを制御するのはとても便利で快感です! お時間ある方は是非チャレンジしてみてはいかがでしょうか? 設計や構築方法について疑問がある方は質問していただければ可能な限りお答えしたいと思います!
kubeadmを用いたKubernetes HAクラスタ on AWS(v.1.11対応版)
前の記事を公開してすぐにv.1.11が出てしまい、構築方法が変わったので、泣きながら再検証...
構成
前提
- 作業ユーザは
root
手順
NLBの作成(AWS ManagementConsole等)
(6443/TCPのリスナを作成、aws-k8s-master[01-03]のIPをターゲットグループに登録する)
Dockerのインストール(aws-k8s-master[01-03]、aws-k8s-node[01-03])
yum install -y docker systemctl enable docker && systemctl start docker
kubeadm、kubelet、kubectlのインストール(aws-k8s-master[01-03]、aws-k8s-node[01-03])
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [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 EOF sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config setenforce 0 yum install -y kubelet kubeadm kubectl systemctl enable kubelet && systemctl start kubelet
cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system
最初のMasterサーバの構築(aws-k8s-master01)
cat <<EOF > kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1alpha2 kind: MasterConfiguration kubernetesVersion: v1.11.0 apiServerCertSANs: - "<NLBのDNS名>" api: controlPlaneEndpoint: "<NLBのDNS名>:6443" etcd: local: extraArgs: listen-client-urls: "https://127.0.0.1:2379,https://<aws-k8s-master01のIP>:2379" advertise-client-urls: "https://<aws-k8s-master01のIP>:2379" listen-peer-urls: "https://<aws-k8s-master01のIP>:2380" initial-advertise-peer-urls: "https://<aws-k8s-master01のIP>:2380" initial-cluster: "aws-k8s-master01=https://<aws-k8s-master01のIP>:2380" serverCertSANs: - aws-k8s-master01 - <aws-k8s-master01のIP> peerCertSANs: - aws-k8s-master01 - <aws-k8s-master01のIP> networking: podSubnet: "192.168.0.0/16" EOF
kubeadm init --config kubeadm-config.yaml mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config
SSHキーペアの作成(aws-k8s-master02, aws-k8s-master03)
ssh-keygen -t rsa -b 4096 -C ""
cat ~/.ssh/id_rsa.pub # 出力された内容をaws-k8s-master01の/root/.ssh/authorized_keysのエントリを追加する
証明書群、設定ファイル群の配布(aws-k8s-master02、aws-k8s-master03)
mkdir -p /etc/kubernetes/pki/etcd scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/ca.crt scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/ca.key /etc/kubernetes/pki/ca.key scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/sa.key /etc/kubernetes/pki/sa.key scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/sa.pub /etc/kubernetes/pki/sa.pub scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/front-proxy-ca.crt /etc/kubernetes/pki/front-proxy-ca.crt scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/front-proxy-ca.key /etc/kubernetes/pki/front-proxy-ca.key scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/etcd/ca.crt /etc/kubernetes/pki/etcd/ca.crt scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/etcd/ca.key /etc/kubernetes/pki/etcd/ca.key scp root@<aws-k8s-master01のIP>:/etc/kubernetes/admin.conf /etc/kubernetes/admin.conf
2台目のMasterサーバの構築(aws-k8s-master02)
cat <<EOF > kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1alpha2 kind: MasterConfiguration kubernetesVersion: v1.11.0 apiServerCertSANs: - "<NLBのDNS名>" api: controlPlaneEndpoint: "<NLBのDNS名>:6443" etcd: local: extraArgs: listen-client-urls: "https://127.0.0.1:2379,https://<aws-k8s-master02のIP>:2379" advertise-client-urls: "https://<aws-k8s-master02のIP>:2379" listen-peer-urls: "https://<aws-k8s-master02のIP>:2380" initial-advertise-peer-urls: "https://<aws-k8s-master02のIP>:2380" initial-cluster: "aws-k8s-master01=https://<aws-k8s-master01のIP>:2380,aws-k8s-master02=https://<aws-k8s-master02のIP>:2380" initial-cluster-state: existing serverCertSANs: - aws-k8s-master02 - <aws-k8s-master02のIP> peerCertSANs: - aws-k8s-master02 - <aws-k8s-master02のIP> networking: podSubnet: "192.168.0.0/16" EOF
kubeadm alpha phase certs all --config kubeadm-config.yaml kubeadm alpha phase kubelet config write-to-disk --config kubeadm-config.yaml kubeadm alpha phase kubelet write-env-file --config kubeadm-config.yaml kubeadm alpha phase kubeconfig kubelet --config kubeadm-config.yaml systemctl start kubelet
CP0_IP=<aws-k8s-master01のIP> CP0_HOSTNAME=aws-k8s-master01 CP1_IP=<aws-k8s-master02のIP> CP1_HOSTNAME=aws-k8s-master02 KUBECONFIG=/etc/kubernetes/admin.conf kubectl exec -n kube-system etcd-${CP0_HOSTNAME} -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://${CP0_IP}:2379 member add ${CP1_HOSTNAME} https://${CP1_IP}:2380 kubeadm alpha phase etcd local --config kubeadm-config.yaml
kubeadm alpha phase kubeconfig all --config kubeadm-config.yaml kubeadm alpha phase controlplane all --config kubeadm-config.yaml kubeadm alpha phase mark-master --config kubeadm-config.yaml
3台目のMasterサーバの構築(aws-k8s-master03)
cat <<EOF > kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1alpha2 kind: MasterConfiguration kubernetesVersion: v1.11.0 apiServerCertSANs: - "<NLBのDNS名>" api: controlPlaneEndpoint: "<NLBのDNS名>:6443" etcd: local: extraArgs: listen-client-urls: "https://127.0.0.1:2379,https://<aws-k8s-master03のIP>:2379" advertise-client-urls: "https://<aws-k8s-master03のIP>:2379" listen-peer-urls: "https://<aws-k8s-master03のIP>:2380" initial-advertise-peer-urls: "https://<aws-k8s-master03のIP>:2380" initial-cluster: "aws-k8s-master01=https://<aws-k8s-master01のIP>:2380,aws-k8s-master02=https://<aws-k8s-master02のIP>:2380,aws-k8s-master03=https://<aws-k8s-master03のIP>:2380" initial-cluster-state: existing serverCertSANs: - aws-k8s-master03 - <aws-k8s-master03のIP> peerCertSANs: - aws-k8s-master03 - <aws-k8s-master03のIP> networking: podSubnet: "192.168.0.0/16" EOF
kubeadm alpha phase certs all --config kubeadm-config.yaml kubeadm alpha phase kubelet config write-to-disk --config kubeadm-config.yaml kubeadm alpha phase kubelet write-env-file --config kubeadm-config.yaml kubeadm alpha phase kubeconfig kubelet --config kubeadm-config.yaml systemctl start kubelet
CP0_IP=<aws-k8s-master01のIP> CP0_HOSTNAME=aws-k8s-master01 CP2_IP=<aws-k8s-master03のIP> CP2_HOSTNAME=aws-k8s-master03 KUBECONFIG=/etc/kubernetes/admin.conf kubectl exec -n kube-system etcd-${CP0_HOSTNAME} -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://${CP0_IP}:2379 member add ${CP2_HOSTNAME} https://${CP2_IP}:2380 kubeadm alpha phase etcd local --config kubeadm-config.yaml
kubeadm alpha phase kubeconfig all --config kubeadm-config.yaml kubeadm alpha phase controlplane all --config kubeadm-config.yaml kubeadm alpha phase mark-master --config kubeadm-config.yaml
flannelのインストール(aws-k8s-master01)
curl -O https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml sed -i 's/10.244.0.0/192.168.0.0/g' kube-flannel.yml kubectl apply -f kube-flannel.yml
Nodeのクラスタ参加(aws-k8s-node[01-03])
kubeadm join --token <token> <NLBのDNS名>:6443 --discovery-token-ca-cert-hash sha256:<hash> # <token>、<hash>はkubeadm initをaws-k8s-master01で実行した際に表示されたものを使用
kubeadmを用いたKubernetes HAクラスタ on AWS
AWS上でkubeadm
を使い、Kubernetes HAクラスタを作ってみたときのメモです。
構成
前提
- 作業ユーザは
root
手順
Dockerのインストール(aws-k8s-master[01-03]、aws-k8s-node[01-03])
yum install -y docker systemctl enable docker && systemctl start docker
kubeadm、kubelet、kubectlのインストール(aws-k8s-master[01-03]、aws-k8s-node[01-03])
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [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 EOF sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config setenforce 0 yum install -y kubelet kubeadm kubectl systemctl enable kubelet && systemctl start kubelet
cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system
cfssl、cfssljsonのインストール(aws-k8s-master[01-03])
curl -o /usr/local/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 curl -o /usr/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x /usr/local/bin/cfssl*
etcdサーバのためのCA証明書作成(aws-k8s-master01)
mkdir -p /etc/etcd/pki cd /etc/etcd/pki cat >ca-config.json <<EOF { "signing": { "default": { "expiry": "175200h" }, "profiles": { "server": { "expiry": "175200h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] }, "client": { "expiry": "175200h", "usages": [ "signing", "key encipherment", "client auth" ] }, "peer": { "expiry": "175200h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF # 証明書の有効期限は20年
cat >ca-csr.json <<EOF { "CN": "etcd", "key": { "algo": "rsa", "size": 2048 } } EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
etcdのクライアント証明書の作成(aws-k8s-master01)
cat >client.json <<EOF { "CN": "client", "key": { "algo": "ecdsa", "size": 256 } } EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
環境変数のエクスポート(aws-k8s-master[01-03])
export PEER_NAME=$(hostname) export PRIVATE_IP=$(ip addr show eth0 | grep -Po 'inet \K[\d.]+')
SSHキーペアの作成(aws-k8s-master02, aws-k8s-master03)
ssh-keygen -t rsa -b 4096 -C ""
cat ~/.ssh/id_rsa.pub # 出力された内容をaws-k8s-master01の/root/.ssh/authorized_keysのエントリを追加する
CA証明書とクライアント証明書の配布(aws-k8s-master02, aws-k8s-master03)
mkdir -p /etc/etcd/pki cd /etc/etcd/pki scp root@<aws-k8s-master01のIP>:/etc/etcd/pki/ca.pem . scp root@<aws-k8s-master01のIP>:/etc/etcd/pki/ca-key.pem . scp root@<aws-k8s-master01のIP>:/etc/etcd/pki/client.pem . scp root@<aws-k8s-master01のIP>:/etc/etcd/pki/client-key.pem . scp root@<aws-k8s-master01のIP>:/etc/etcd/pki/ca-config.json .
etcdサーバ証明書とpeer証明書の作成(aws-k8s-master[01-03])
cfssl print-defaults csr > config.json sed -i '0,/CN/{s/example\.net/'"$PEER_NAME"'/}' config.json sed -i 's/www\.example\.net/'"$PRIVATE_IP"'/' config.json sed -i 's/example\.net/'"$PEER_NAME"'/' config.json
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server config.json | cfssljson -bare server cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer config.json | cfssljson -bare peer
etcdサーバのsystemd登録と起動設定(aws-k8s-master[01-03])
export ETCD_VERSION="v3.1.12" curl -sSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xzv --strip-components=1 -C /usr/local/bin/
touch /etc/etcd.env echo "PEER_NAME=${PEER_NAME}" >> /etc/etcd.env echo "PRIVATE_IP=${PRIVATE_IP}" >> /etc/etcd.env
cat >/etc/systemd/system/etcd.service <<EOF [Unit] Description=etcd Documentation=https://github.com/coreos/etcd Conflicts=etcd.service Conflicts=etcd2.service [Service] EnvironmentFile=/etc/etcd.env Type=notify Restart=always RestartSec=5s LimitNOFILE=40000 TimeoutStartSec=0 ExecStart=/usr/local/bin/etcd --name <name> --data-dir /var/lib/etcd --listen-client-urls https://<my_ip>:2379 --advertise-client-urls https://<my_ip>:2379 --listen-peer-urls https://<my_ip>:2380 --initial-advertise-peer-urls https://<my_ip>:2380 --cert-file=/etc/etcd/pki/server.pem --key-file=/etc/etcd/pki/server-key.pem --client-cert-auth --trusted-ca-file=/etc/etcd/pki/ca.pem --peer-cert-file=/etc/etcd/pki/peer.pem --peer-key-file=/etc/etcd/pki/peer-key.pem --peer-client-cert-auth --peer-trusted-ca-file=/etc/etcd/pki/ca.pem --initial-cluster aws-k8s-master01=https://<aws-k8s-master01のIP>:2380,aws-k8s-master02=https://<aws-k8s-master02のIP>:2380,aws-k8s-master03=https://<aws-k8s-master03のIP>:2380 --initial-cluster-token my-etcd-token --initial-cluster-state new # <name>にはaws-k8s-master[01-03]が入る [Install] WantedBy=multi-user.target EOF
systemctl daemon-reload systemctl enable etcd systemctl start etcd
NLBの作成(AWS ManagementConsole等)
(6443/TCPのリスナを作成、aws-k8s-master01のインスタンスをターゲットグループに登録する)
(NLB作成後、DNS名にpingを発行し、NLBのIPを確認する)
kubeadmの実行(aws-k8s-master01)
cat >config.yaml <<EOF apiVersion: kubeadm.k8s.io/v1alpha1 kind: MasterConfiguration etcd: endpoints: - https://<aws-k8s-master01のIP>:2379 - https://<aws-k8s-master02のIP>:2379 - https://<aws-k8s-master03のIP>:2379 caFile: /etc/etcd/pki/ca.pem certFile: /etc/etcd/pki/client.pem keyFile: /etc/etcd/pki/client-key.pem networking: podSubnet: 192.168.0.0/16 apiServerCertSANs: - <NLBのIP> - <my_ip> apiServerExtraArgs: apiserver-count: "3" EOF
kubeadm init --config=config.yaml
mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config
kubeadmの実行(aws-k8s-master02,aws-k8s-master03)
mkdir /etc/kubernetes/pki scp root@<aws-k8s-master01のIP>:/etc/kubernetes/pki/* /etc/kubernetes/pki rm -f /etc/kubernetes/pki/apiserver*
cat >config.yaml <<EOF apiVersion: kubeadm.k8s.io/v1alpha1 kind: MasterConfiguration etcd: endpoints: - https://<aws-k8s-master01のIP>:2379 - https://<aws-k8s-master02のIP>:2379 - https://<aws-k8s-master03のIP>:2379 caFile: /etc/etcd/pki/ca.pem certFile: /etc/etcd/pki/client.pem keyFile: /etc/etcd/pki/client-key.pem networking: podSubnet: 192.168.0.0/16 apiServerCertSANs: - <NLBのIP> - <my_ip> apiServerExtraArgs: apiserver-count: "3" EOF
kubeadm init --config=config.yaml
mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config
NLBへ残りのMasterを追加(AWS ManagementConsole等)
(NLBのターゲットグループにaws-k8s-master02、aws-k8s-master03を追加)
calicoのインストール(aws-k8s-master01)
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
Nodeのクラスタ参加(aws-k8s-node[01-03])
kubeadm join --token <token> <aws-k8s-master01のIP>:6443 --discovery-token-ca-cert-hash sha256:<hash> # <token>、<hash>はkubeadm initをaws-k8s-master01で実行した際に表示されたものを使用
kube-proxyの再設定(aws-k8s-master01)
kubectl get configmap -n kube-system kube-proxy -o yaml > kube-proxy-cm.yaml sed -i 's#server:.*#server: https://<NLBのIP>:6443#g' kube-proxy-cm.yaml kubectl apply -f kube-proxy-cm.yaml --force kubectl delete pod -n kube-system -l k8s-app=kube-proxy
kubeletの再設定(aws-k8s-node[01-03])
sed -i 's#server:.*#server: https://<NLBのIP>:6443#g' /etc/kubernetes/kubelet.conf systemctl restart kubelet
gVisorを試してみた
Googleが開発したgVisorを試して、簡単に性能調査してみましたので、メモとして残しておきます。
環境
gVisorのインストール手順
- Dockerのインストール
sudo apt-get update sudo apt-get install -y \ apt-transport-https \ ca-certificates \ curl \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install -y docker-ce
- gVisor(runsc)のインストール
wget https://storage.googleapis.com/gvisor/releases/nightly/latest/runsc chmod +x runsc sudo mv runsc /usr/local/bin sudo sh -c 'cat <<EOF > /etc/docker/daemon.json { "runtimes": { "runsc": { "path": "/usr/local/bin/runsc" } } } EOF' sudo systemctl restart docker
- コンテナを起動してみる
sudo docker run --runtime=runc hello-world sudo docker run --runtime=runsc hello-world
性能調査
簡単なスクリプトでコンテナ起動と削除のスピードを評価します。
cat <<EOF > runc-test.sh for i in \$(seq 1 \$1) ; do sudo docker run --runtime=runc --name gvisor-test hello-world > /dev/null 2>&1 sudo docker rm gvisor-test > /dev/null 2>&1 done EOF chmod +x runc-test.sh cat <<EOF > runsc-test.sh for i in \$(seq 1 \$1) ; do sudo docker run --runtime=runsc --name gvisor-test hello-world > /dev/null 2>&1 sudo docker rm gvisor-test > /dev/null 2>&1 done EOF chmod +x runsc-test.sh
スクリプトの使い方としては./runc-test.sh <起動および削除回数>
、./runsc-test.sh <起動および削除回数>
とします。試しに両方100回ずつ起動・削除を繰り返すと、以下のような結果となりました。
ubuntu@gvisor-01:~$ time ./runc-test.sh 100 real 1m20.991s user 0m14.948s sys 0m1.768s ubuntu@gvisor-01:~$ time ./runsc-test.sh 100 real 1m13.219s user 0m15.100s sys 0m1.748s
起動・停止だけではrunc
とあまり差はみられませんね。むしろrunsc
の方が速い?
ネットワークトラフィックの差をとるとrunc
に軍配が上がるみたいですが。。。
追記(2018/06/07) 気になってDisk書き込み速度も調べてみましたが、逆転現象が起きましたw
- runc
root@4aee2e622884:/# dd if=/dev/zero of=/tmp/write.tmp ibs=1M obs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 4.17698 s, 257 MB/s
- runsc
root@ce7e3926f52e:/# dd if=/dev/zero of=/tmp/write.tmp ibs=1M obs=1M count=1024 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.853382 s, 1.3 GB/s
Rancher 2.0で複数のKubernetes環境を管理してみる
2018年4月末にコンテナ管理プラットフォームであるRancherのバージョン2.0がGA(General Availability)となりました。対応するコンテナオーケストレーションツールをKubernetesに絞り、オンプレ/クラウド問わずKubernetesクラスタをマネジメントするOSSに昇華されているみたいです。今回はこのRancher 2.0を使って
というところまでをやってみたいと思います。
環境
今回は以下の環境で試用してみます。
- OS
- CentOS 7.4
- Rancher
- Ver: v2.0.2
- インポートするKubernetes
- Ver: 1.10.0
- RKE(Rancher Kubernetes Engine)のKubernetes
- Ver: 1.10.1
- 構成サーバ群
- Rancherサーバ : rancher-server-01
- RKE k8sマスター: rancher-k8s-master-01
- RKE k8sノード#1: rancher-k8s-node-01
- RKE k8sノード#2: rancher-k8s-node-02
- 自前k8sマスター: tst-k8s-master01
- 自前k8sノード#1: tst-k8s-node01
- 自前k8sノード#2: tst-k8s-node02
事前準備
今回は検証なので、ポートは全開放でいきます。以下のコマンドを全ノードで叩きます。
firewall-cmd --set-default-zone=trusted
次に全ノードにDockerをインストールして、サービスを起動します。
yum -y install docker systemctl enable docker systemctl start docker
この時点でインポートする自前k8sを構築しておきます。注意点としては、kube-dns
とIngress Controllerを忘れずにデプロイしておきます。
Rancherサーバの構築
Rancherサーバを構築していきますが、難しいことはありません。以下のコマンドを叩くだけです。
mkdir /var/lib/rancher docker run -d --restart=unless-stopped -p 80:80 -p 443:443 -v /var/lib/rancher:/var/lib/rancher:Z rancher/rancher:v2.0.2
ここで/var/lib/rancher
はRancherサーバの永続ボリュームとして使うディレクトリなので、お好みで調整してください。
またCentOSをはじめとしたRHEL系OSではSELinuxが有効になっているかと思いますので、-v
オプションの末尾に:Z
をつけて適切なラベリングを行うようにしておきます。
Rancherサーバが起動したら、ウェブブラウザからRancherサーバにログインします。するとまずadmin
ユーザのパスワードを作成するよう求められるので、パスワードを入力して次に進みます。
RancherサーバのURLはアクセスした際のURLがデフォルトで表示されていますので、そのままで次に進みます。
すると以下のような画面が表示されます。クラスタを登録する前にHelm(k8sのパッケージマネージャ)を有効化しておきましょう。「Catalog」を選択します。
「Helm Stable」のスイッチを「Enabled」にします。
これでHelmの有効化は完了です。
新しいKubernetesクラスタの作成
次にクラスタを登録していきましょう。まずはRKEクラスタを作成・登録します。「Clusters」を選択し、「Add Cluster」をクリックします。
すると以下のような画面になります。今回は一般的な仮想マシンからk8sクラスタを作成しますので、「CUSTOM」を選択し、「Next」をクリックします。
次の画面ではRKE k8sクラスタを作成するのに必要なコマンドが表示されます。k8sマスターを登録をするには「Node Role」の
- etcd
- Control
- Worker
にチェックを入れ、記載されているコマンドを実行します。が、SELinuxが有効な環境に対してはこのままではダメで、-v
オプションの末尾に:Z
をつけるのを忘れないようにしましょう。
同様にk8sノードを登録するには「Node Role」の
- Worker
にチェックを入れ、記載されているコマンドを実行します。-v
オプションの末尾に:Z
をつけるのを忘れずに。
それぞれのサーバでコマンド実行が終わったら「Done」をクリックします。そうするとRKE k8sクラスタの作成が始まります。
既存のKubernetesクラスタのインポート
RKE k8sクラスタの作成を待っている間に既存k8sクラスタをRancherサーバにインポートしましょう。「Clusters」を選択して「Add Cluster」をクリックし、今度は「IMPORT」を選択します。その後「Next」をクリックしましょう。
すると既存k8sクラスタをRancherサーバに登録するためのコマンドが発行されますので、k8sマスター上で二番目のコマンドを叩きます。叩いたら「Done」をクリックします。
戻った画面で「State」の値が「Active」になっていればRKE k8sクラスタの作成・登録、既存k8sクラスタの登録は完了です。
Helmでアプリケーションをデプロイ
Rancherに二つのk8sクラスタが登録されたので、それぞれのクラスタ上にアプリケーションをデプロイしてみましょう。まずはRKE k8sクラスタ上にデプロイしてみます。「Global」から「Cluster: rke-cluster-01 > Default」をクリックします。
「Catalog Apps」を選択し、「Launch」をクリックします。
表示されたカタログ群から「dokuwiki」を選択します。
今回はPersistent Volumeをまだサポートしていないクラスタなので、アプリケーションのデプロイでPersistent Volumeを使わない設定にします。またデフォルトではLoadBalancer
タイプのServiceが作られるので、これをClusterIP
に変更します。下のほうに進んで「Add Answer」を2回クリックし、以下のKey-Valueを入力します。その後「Launch」をクリックします。
- serviceType = ClusterIP
- persistence.enabled = false
しばらくすると以下のようにゲージが緑になります。この状態になれば必要なPodは上がっている状態です。
では、Ingressを作成して外部からdokuwikiにアクセスできるようにしましょう。「Workloads」を選択し「Load Balancing」タブを選んでから「Add Ingress」をクリックします。
Ingressを作成する際のパラメータは以下の通りにします。
- Name: (任意の名前)
- Namespace: (作成されたNamespace)
- Rules
- Automatically generate a
.xip.io
hostname - Target: (作成されたService)
- Port: 80
- Automatically generate a
以上、入力したら下の「Save」をクリックします。少し経つと以下の通りURLが発行されるので、アクセスしてみましょう。dokuwikiのホームページが表示されます!
次は既存k8sクラスタ上にアプリケーションをデプロイしてみます。「Global」から「Cluster: my-cluster-01 > Default」をクリックします。
「Catalog Apps」を選択し、「Launch」をクリックします。
表示されたカタログ群から「zeppelin」を選択します。
このカタログではデフォルトのCPU・メモリリソースを最低2000millicore、4096MiB確保するように設定されているので、今回構築したクラスタで展開できる値に修正します。「Add Answer」を2回クリックし、以下のKey-Valueを入力します。その後「Launch」をクリックします。
- zeppelin.resources.limits.cpu: 1000m
- zeppelin.resources.limits.meory: 2048Mi
ゲージが緑になるまで待ちましょう。
dokuwikiと同様、Ingressを作っていきます。「Workloads」を選択し「Load Balancing」タブを選んでから「Add Ingress」をクリックします。
Ingressを作成する際のパラメータは以下の通りにします。
- Name: (任意の名前)
- Namespace: (作成されたNamespace)
- Rules
- Specify a hostname use
- Request Host: (Ingress Controllerに対応した名前)
- Target: (作成されたService)
- Port: 8080
- Specify a hostname use
以上、入力したら下の「Save」をクリックします。表示されたURLにアクセスしてみましょう。zeppelinのホームページが表示されます!
API Aggregationを有効化してPrometheusのメトリクスからHorizonPodAutoscalerでPodのオートスケールをする
やたら長いタイトルですが…
KubernetesではAPI Aggregationといって、Custom Metrics API Serverを用意しkube-apiserver
と連携することでAPIを拡張することができます。例えば今回のタイトルにもある通り、Prometheusが取得したメトリクスをAPIから取得できるようにすることができます。この記事では以下を可能とするKubernetesの設定を説明します。
API Aggregationの有効化
API Aggregationを有効化するにはkube-apiserver
とkube-controller-manager
に設定が必要になります。
まず、kube-controller-manager
に以下のオプションを設定して再起動します。
--horizontal-pod-autoscaler-use-rest-clients=true
次にkube-apiserver
の認証方式において、x509証明書認証を有効化するために、CA証明書を用意します。CA証明書のファイルパスを/etc/kubernetes/certs/ca.crt
とします。
さらにkube-apiserver
とCustom Metrics API Serverとが連携するために使うクライアント証明書と秘密鍵、そしてクライアント証明書の署名に使ったCAのCA証明書を用意します。それぞれのファイルパスを/etc/kubernetes/certs/proxy-client.crt
、/etc/kubernetes/certs/proxy-client.key
、/etc/kubernetes/certs/proxy-ca.crt
とします。
その後kube-apiserver
に以下のオプションを設定します
--client-ca-file=/etc/kubernetes/certs/ca.crt --requestheader-client-ca-file=/etc/kubernetes/certs/proxy-ca.crt --requestheader-allowed-names='' --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --proxy-client-cert-file=/etc/kubernetes/certs/proxy-client.crt --proxy-client-key-file=/etc/kubernetes/certs/proxy-client.key
最後にkube-apiserver
の再起動を行うのですが、もし既に--client-ca-file
の値を指定していて今回CA証明書を変更する場合、既にAPIサーバ間連携に使用するConfigMap extension-apiserver-authentication
ができてしまっているので、これをあらかじめ削除しておきます。
kubectl -n kube-system delete configmap extension-apiserver-authentication
その後、kube-apiserver
を再起動します。
これでAPI Aggregationの設定は完了です。
Prometheus用のCustom Metrics API Serverの構築とkube-apiserverとの連携
Prometheus用のCustom Metrics API Serverを構築し、kube-apiserverにAPIエンドポイントを作成してkube-apiserver
とCustom Metrics API Serverとを連携させます。
前提条件として名前空間kube-system
にPrometheusは構築済みであるとします。ここではPrometheusサーバ(port: 9090)のホスト名をprometheus-server
であるとします。
まずはCustom Metrics API Serverを構築するためのKubernetes Manifestをダウンロードします。
git clone https://github.com/DirectXMan12/k8s-prometheus-adapter cd k8s-prometheus-adapter
ダウンロードしてきたManifestの中にあるPrometheusサーバの指定を変更します。
sed -i 's/prometheus.prom.svc:9090/prometheus-server/g' deploy/manifests/custom-metrics-apiserver-deployment.yaml
また、Manifest内でリソースを作成する名前空間をkube-system
に変更します。
sed -i 's/namespace: custom-metrics/namespace: kube-system/g' deploy/manifests/*
さらにPullしてくるCustom Metrics API Serverコンテナイメージのタグを付与します。
sed -i 's/directxman12\/k8s-prometheus-adapter/directxman12\/k8s-prometheus-adapter:advanced-config/g' deploy/manifests/custom-metrics-apiserver-deployment.yaml
次にCustom Metrics API Serverのサーバ証明書と秘密鍵を作成します。ファイル名はそれぞれserving.crt
、serving.key
とします。
作成したサーバ証明書と秘密鍵を使用してSecret cm-adapter-serving-certs
を作成します。
kubectl -n kube-system create secret generic --from-file=serving.crt=serving.crt --from-file=serving.key=serving.key cm-adapter-serving-certs
最後にCustom Metrics API Serverを構築します。
kubectl create -f deploy/manifests/
構築がうまくいっていれば、APIを叩くと以下のような出力が得られると思います。
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [ { "name": "pods/fs_sector_writes", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] }, <中略> { "name": "jobs.batch/kube_pod_status_phase", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] } ] }
PrometheusのメトリクスからPodをオートスケールする
では実際に構築したCustom Metrics API Serverを使ってオートスケールを実現してみましょう。 まずはテスト用にDeployment、Serviceを作ります。
kubectl create deploy httpd --image httpd kubectl expose deploy httpd --port 80 kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd ClusterIP 172.16.132.62 <none> 80/TCP 10s kubernetes ClusterIP 172.16.0.1 <none> 443/TCP 56m
次にHorizontalPodAutoScalerをDeployment httpd
に対して作ります。
cat << EOF > hpa-httpd.yaml apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: httpd namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: httpd minReplicas: 1 maxReplicas: 8 metrics: - type: Pods pods: metricName: cpu_usage targetAverageValue: 1m EOF kubectl create -f hpa-httpd.yaml
HPAが作成出来たら、以下のスクリプトを実行してPodに負荷をかけます。
cat << EOF > hpa-test.sh #!/bin/sh count=1 while(true) do curl http://172.16.132.62 > /dev/null 2>&1 & echo access count = \$((count++)) done EOF chmod 755 hpa-test.sh ./hpa-test.sh
するとPodが増えていく様が見て取れるはずです。