最近、kubernetesを自宅PCにインストールしてみました。まだ使い始めて間もないですが、自動的にコンテナをクラスタに配置してくれたり、コンテナ間を接続するためのネットワークの設定をしてくれたりするので、複数PCを持っていると重宝するかもしれません。
インストールする自宅PCですが、今回は2台使用しました。1台はKVMをインストールしたノートPC、もう一台はWindowsのデスクトップPCです。ノートPCにはmaster、node、それぞれに対応するインスタンス(CentOS7)を作成し、kubernetesをインストールしました。デスクトップPCにはVirtualBoxの仮想マシン(CentOS7)をnodeとして作成しました。kubernetesのインストールはこちらを参考にさせていただきました。なお、selinux、firewalldは下記のようにしていずれも無効にしています(master、node共通)。
# setenforce 0
# sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
# systemctl stop firewalld
# systemctl disable firewalld
それぞれのインスタンスに割り当てたりソースですが、CPUは2つ、メモリはmasterに2G、nodeにそれぞれ4Gバイトを割り当てました。
また、kubernetesのパッケージ管理ツールであるhelmと、外部にWEBサーバ(今回はJenkins)を公開するためnginxベースのingress controllerもインストールしました。
helmのインストールは上記サイトからダウンロードし、masterの/usr/local/binに置きました。helm initでtillerというサーバコンポーネントがインストールされてセットアップが完了しますが、helm listなどを実行すると
Error: configmaps is forbidden: User "system:serviceaccount:kube-system:default" cannot list resource "configmaps" in API group "" in the namespace "kube-system"
のようなエラーが出ました。詳しくはわかりませんが、tiller-deployを実行するサービスアカウントがデフォルトではkube-system(名前空間の一つ)のdefaultになり、それがconfigmap(設定情報を管理するところ)にアクセスする権限がない、というエラーのようです。今回はこちらの情報を参考にして、tiller専用のサービスアカウントを作成しました。
ingress controllerについては、こちらを参考に、公開されているインストール用のyaml(mandatory.yaml、service-nodeport.yaml)をkubectlに指定してapplyしました(service-nodeport.yamlにはmasterのIPアドレスを指定)。
また、JenkinsはPersistent Volume Claim(Podからのストレージのリクエスト。これにより動的にクラスタ内のストレージが割り当てられる)でPersistent Volume(クラスタ内で提供するディスクの実体)を取得するため、こちらのサイトやこちらのサイトを参考に、下記のようなyamlを作成し、nfsを使用したPersistent Volumeとそれに割り当てるStorage Class(ディスクのスペックみたいなもので動的に割り当てるPVに指定する必要がある)、及びPVの提供(プロビジョニング)を行うためのサービスアカウントのRBAC(ロールベースのアクセス制御)の設定用yamlを作成しました。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs
provisioner: myhost.net/nfs
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: myhost.net/nfs
- name: NFS_SERVER
value: nfs.myhost.net
- name: NFS_PATH
value: /volume/kuberdisk
volumes:
- name: nfs-client-root
nfs:
server: nfs.myhost.net
path: /volume/kuberdisk
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
作成したStorage Classは下記のコマンドでデフォルトにしました。
kubectl patch storageclass nfs -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
次にJenkinsのインストールです。helm install stable/jenkinsだけでほぼ全自動でインストールされます。インストールが完了すると、パスワードの取得方法などのメッセージが出力されますので、あとはそれに従うだけです。ただ、このままではまだJenkinsのページに外部からアクセスできません。外部からのアクセスをkubernetes内部のIPアドレスに橋渡しするための設定が必要になります。haproxyのようなリバースプロキシ を自前で設置して設定する方法もありますが、今回は先ほどインストールしたingress controllerを使用しました。こちらを使うと簡単にサーバを公開できます。今回は、下記のようなyamlを作成して公開しました。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-conf-for-jenkins
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: jenkins.myhost.net
http:
paths:
- path: /
backend:
serviceName: knotted-anaconda-jenkins
servicePort: 8080
公開といっても、自宅のLAN内からしかアクセスしませんので、7行目でsslによるリダイレクト(デフォルトではhttpがhttpsにリダイレクトされる)を無効にしています。また、今後、公開したいサーバが増えた時のために、ホストのFQDNによってアクセス先を変えたかったので、hostも指定しています(10行目)。jenkins.myhost.netはmasterインスタンスのFQDNで、LAN内専用のDNSサーバのAレコードでmasterのIPアドレスを割り当てました。