OpenShiftのRBACを完全に理解する
OpenShift 全部俺 Advent Calendar 2017
よくわかりにくいと言われがちなOpenShift / KubernetesのRBACについて書いてみましょう。RBACは元々OpenShiftで実装され、それを元にKubernetes側へ実装された経緯があり、OpenShiftのclusterrole
というリソースオブジェクトとKubernetesのclusterrole
リソースの短縮名が衝突してしまっています。そのため、OpenShift側ではclusterrole.rbac
という名前でリソースを指定する必要があります。ちなみに省略しないリソース名はそれぞれclusterrole.authorization.openshift.io
とclusterrole.rbac.authorization.k8s.io
です。
さて本題。事前に定義されているロールの一覧はoc get clusterrole.rbac
で取得できます。
$ oc get clusterrole.rbac NAME AGE admin 12d asb-access 12d asb-auth 12d basic-user 12d cluster-admin 12d cluster-debugger 12d cluster-reader 12d cluster-status 12d edit 12d hawkular-metrics-admin 12d management-infra-admin 12d namespace-viewer 12d registry-admin 12d registry-editor 12d registry-viewer 12d sar-creator 12d self-access-reviewer 12d self-provisioner 12d service-catalog-controller 12d servicecatalog-serviceclass-viewer 12d storage-admin 12d sudoer 12d system:auth-delegator 12d system:basic-user 12d system:build-controller 12d system:build-strategy-custom 12d system:build-strategy-docker 12d system:build-strategy-jenkinspipeline 12d system:build-strategy-source 12d system:certificate-signing-controller 12d system:controller:attachdetach-controller 12d system:controller:certificate-controller 12d system:controller:cronjob-controller 12d system:controller:daemon-set-controller 12d system:controller:deployment-controller 12d system:controller:disruption-controller 12d system:controller:endpoint-controller 12d system:controller:generic-garbage-collector 12d system:controller:horizontal-pod-autoscaler 12d system:controller:job-controller 12d system:controller:namespace-controller 12d system:controller:node-controller 12d system:controller:persistent-volume-binder 12d system:controller:pod-garbage-collector 12d system:controller:replicaset-controller 12d system:controller:replication-controller 12d system:controller:resourcequota-controller 12d system:controller:route-controller 12d system:controller:service-account-controller 12d system:controller:service-controller 12d system:controller:statefulset-controller 12d system:controller:ttl-controller 12d system:daemonset-controller 12d system:deployer 12d system:deployment-controller 12d system:deploymentconfig-controller 12d system:discovery 12d system:disruption-controller 12d system:endpoint-controller 12d system:garbage-collector-controller 12d system:gc-controller 12d system:heapster 12d system:hpa-controller 12d system:image-auditor 12d system:image-builder 12d system:image-pruner 12d system:image-puller 12d system:image-pusher 12d system:image-signer 12d system:job-controller 12d system:kube-aggregator 12d system:kube-controller-manager 12d system:kube-dns 12d system:kube-scheduler 12d system:master 12d system:namespace-controller 12d system:node 12d system:node-admin 12d system:node-bootstrapper 12d system:node-problem-detector 12d system:node-proxier 12d system:node-reader 12d system:oauth-token-deleter 12d system:openshift:controller:build-config-change-controller 12d system:openshift:controller:build-controller 12d system:openshift:controller:cluster-quota-reconciliation-controller 12d system:openshift:controller:deployer-controller 12d system:openshift:controller:deploymentconfig-controller 12d system:openshift:controller:horizontal-pod-autoscaler 12d system:openshift:controller:image-import-controller 12d system:openshift:controller:image-trigger-controller 12d system:openshift:controller:origin-namespace-controller 12d system:openshift:controller:pv-recycler-controller 12d system:openshift:controller:resourcequota-controller 12d system:openshift:controller:sdn-controller 12d system:openshift:controller:service-ingress-ip-controller 12d system:openshift:controller:service-serving-cert-controller 12d system:openshift:controller:serviceaccount-controller 12d system:openshift:controller:serviceaccount-pull-secrets-controller 12d system:openshift:controller:template-instance-controller 12d system:openshift:controller:template-service-broker 12d system:openshift:controller:unidling-controller 12d system:openshift:templateservicebroker-client 12d system:persistent-volume-provisioner 12d system:registry 12d system:replicaset-controller 12d system:replication-controller 12d system:router 12d system:scope-impersonation 12d system:sdn-manager 12d system:sdn-reader 12d system:statefulset-controller 12d system:webhook 12d view 12d
なんだかすごくいっぱい出てきましたが、system:
とついているものはシステムコンポーネントで利用されているロールで利用者視点では真っ先に無視して構わないものです。除外してみます。
$ oc get clusterrole.rbac | grep -v system: NAME AGE admin 12d asb-access 12d asb-auth 12d basic-user 12d cluster-admin 12d cluster-debugger 12d cluster-reader 12d cluster-status 12d edit 12d hawkular-metrics-admin 12d management-infra-admin 12d namespace-viewer 12d registry-admin 12d registry-editor 12d registry-viewer 12d sar-creator 12d self-access-reviewer 12d self-provisioner 12d service-catalog-controller 12d servicecatalog-serviceclass-viewer 12d storage-admin 12d sudoer 12d view 12d
いくつかまだOpenShiftが利用する目的のロールであり利用者には無関係なロールがあるものの、だいぶすっきりしました。
各ロールが実際に何ができるかはdescribeすればわかります。たとえばnamespace-viewer
はnamespace
オブジェクトのget list watch
が許可されているロールです。
$ oc describe clusterrole.rbac namespace-viewer Name: namespace-viewer Labels: <none> Annotations: <none> PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- namespaces [] [] [get list watch]
カスタムのロールを作るときにResourcesやVerbsに何が指定できるかはoc describe clusterrole.rbac
などで全出力を見ればわかるでしょう。カスタムロールはプロジェクト(namespace)固有のものはrole.rbac
として、クラスタ全体で利用したいロールは管理者権限でclusterrole.rbac
として作成します。
ロールの割り当て状況はoc get clusterrolebinding.rbac -o wide
を確認するとわかります。割り当てられていないロールは非表示となるので注意しましょう。以下system:
を除外した結果です。
$ oc get clusterrolebinding.rbac -o wide | grep -v system: NAME AGE ROLE USERS GROUPS SERVICEACCOUNTS admin 12d admin openshift-infra/template-instance-controller, kube-service-catalog/default, openshift-ansible-service-broker/asb asb-access 12d asb-access openshift-ansible-service-broker/asb-client asb-auth 12d asb-auth openshift-ansible-service-broker/asb hawkular-metrics-admin 12d hawkular-metrics-admin management-infra/management-admin management-infra-admin 12d management-infra-admin management-infra/management-admin service-catalog-controller-binding 12d service-catalog-controller kube-service-catalog/service-catalog-controller service-catalog-controller-namespace-viewer-binding 12d namespace-viewer kube-service-catalog/service-catalog-controller service-catalog-namespace-viewer-binding 12d namespace-viewer kube-service-catalog/service-catalog-apiserver service-catalog-sar-creator-binding 12d sar-creator kube-service-catalog/service-catalog-apiserver
User, Group, Service Accountというのが出てきました。ユーザは一般的なユーザ、およびシステムユーザが含まれます。グループは一般的なグループ、システムグループ、特殊なシステムグループであるバーチャルグループがあります。
system:admin
などのシステムユーザやシステムグループのドキュメントや一覧は用意されていませんが、なんとなく名前で役割はわかると思います。これらはソースコード中にハードコードされているので、oc get user
, oc get group
では表示されず、上記のclusterrolebinding.rbac
の出力が唯一の手掛かりとなります。
system:authenticated
やsystem:unauthenticated
は名前の通り、認証済みユーザ、認証していないユーザを表すバーチャルシステムグループです。これを利用して、例えばsystem:unauthenticated
にregistry-viewer
を付与すると、そのプロジェクトのコンテナイメージは認証なしでpullできる状態となります。
Userは人間が操作するユーザに割り当てるのに対し、Service Account (SA)は、Podに割り当てるユーザです。権限設定が必要なPodや、tokenを抜き出して外部から操作したりといった各種自動化などに利用されます。たとえば各プロジェクトにはdefault
, builder
, deployer
というSAが自動的に作成され、deployer
にはプロジェクトのロールとしてsystem:deployer
が設定されます。これはoc get rolebinding.rbac -o wide
で確認できます。確認するとわかりますが、Podがデフォルトで利用するSAであるdefault
は初期状態ではロールが割り当てられていない一般ユーザとなり、Kubernetes APIへのアクセスは一切できません。
一般的に利用されるロールを軽く説明します。
cluster-admin
- クラスタ管理者権限。一般ユーザに付与するには
oc adm policy add-cluster-role-to-user cluster-admin USERNAME
。
- クラスタ管理者権限。一般ユーザに付与するには
cluster-reader
view
,edit
,admin
registry-viewer
,registry-editor
- プロジェクト内のコンテナイメージのpullおよびpull/push権限。別プロジェクトのSAに付与して利用する。
というわけで、以下の4つさえ押さえておけばRBAC完璧です。
OpenShiftのPipelineビルドで利用するイメージをカスタマイズする
OpenShift 全部俺 Advent Calendar 2017
Google Home買いました。日本語設定でいろいろやってみて、3歳児が「おーけーぐるぐる、てべりをちゅけてください、おねがいします!」と話しかけてるのを一通り楽しんでから英語設定にスイッチして使ってます。これで子供が英語覚えたりするかな。まぁしないだろうな。
前回Jenkins PipelineジョブをSlaveとなる別のPodで実行しました。今回はこのslave podをカスタマイズしてみましょう。ドキュメントは以下のURLです。
https://docs.openshift.org/3.11/using_images/other_images/jenkins.html
https://github.com/jenkinsci/kubernetes-plugin
config.xml
にデフォルトの定義maven
とnode
があるので、それをコピーして新しい設定を作成します。適当にgrepして一つ目を取り出してみます。ConfigMapに突っ込むファイルはCRLFだとEditするときにひどいことになるのでLFに変換します。
$ oc rsh dc/jenkins cat /var/lib/jenkins/config.xml | grep -m1 -A33 PodTemplate | perl -pe 's/^\s{8}//' | dos2unix > pod-template.xml
中身はmaven
のもので、以下のような定義となっています。
<org.csanchez.jenkins.plugins.kubernetes.PodTemplate> <inheritFrom></inheritFrom> <name>maven</name> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <instanceCap>2147483647</instanceCap> <slaveConnectTimeout>0</slaveConnectTimeout> <idleMinutes>0</idleMinutes> <label>maven</label> <serviceAccount>jenkins</serviceAccount> <nodeSelector></nodeSelector> <customWorkspaceVolumeEnabled>false</customWorkspaceVolumeEnabled> <volumes/> <containers> <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <name>jnlp</name> <image>openshift/jenkins-slave-maven-centos7</image> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <workingDir>/tmp</workingDir> <command></command> <args>${computer.jnlpmac} ${computer.name}</args> <ttyEnabled>false</ttyEnabled> <resourceRequestCpu></resourceRequestCpu> <resourceRequestMemory></resourceRequestMemory> <resourceLimitCpu></resourceLimitCpu> <resourceLimitMemory></resourceLimitMemory> <envVars/> </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> </containers> <envVars/> <annotations/> <imagePullSecrets/> </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
name
が作成されるslave pod名、label
がPipelineで指定するslaveのラベル名になっています。
両方custom-maven
に変更して、環境変数を追加してビルドしてみましょう。
<org.csanchez.jenkins.plugins.kubernetes.PodTemplate> <inheritFrom></inheritFrom> <name>custom-maven</name> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <instanceCap>2147483647</instanceCap> <slaveConnectTimeout>0</slaveConnectTimeout> <idleMinutes>0</idleMinutes> <label>custom-maven</label> <serviceAccount>jenkins</serviceAccount> <nodeSelector></nodeSelector> <customWorkspaceVolumeEnabled>false</customWorkspaceVolumeEnabled> <volumes/> <containers> <org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> <name>jnlp</name> <image>openshift/jenkins-slave-maven-centos7</image> <privileged>false</privileged> <alwaysPullImage>false</alwaysPullImage> <workingDir>/tmp</workingDir> <command></command> <args>${computer.jnlpmac} ${computer.name}</args> <ttyEnabled>false</ttyEnabled> <resourceRequestCpu></resourceRequestCpu> <resourceRequestMemory></resourceRequestMemory> <resourceLimitCpu></resourceLimitCpu> <resourceLimitMemory></resourceLimitMemory> <envVars> <org.csanchez.jenkins.plugins.kubernetes.PodEnvVar> <key>foo</key> <value>bar</value> </org.csanchez.jenkins.plugins.kubernetes.PodEnvVar> </envVars> </org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate> </containers> <envVars/> <annotations/> <imagePullSecrets/> </org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
role=jenkins-slave
というラベルが付与されているConfigMapに入れるとOpenShift Jenkins Sync Pluginが勝手に反映してくれるようになっています。
$ vi pod-template.xml $ oc create configmap jenkins-slave --from-file=pod-template.xml $ oc label configmap jenkins-slave role=jenkins-slave $ oc start-build test-pipeline
これで生成されたcustom-maven-XXXXというPodではfoo=bar
という環境変数が設定されている状態となります。Pipelineでsh "echo $foo"
など実行することで確認できます。
OpenShiftでJenkins Pipelineビルドを利用する
OpenShift 全部俺 Advent Calendar 2017
OpenShiftにはソースコードからビルドするs2iビルド、Dockerfileを利用してビルドするDockerビルドの他にJenkinsを利用したPipelineビルドというのがあります。s2iビルドやDockerビルドはコンテナイメージを生成してpushする、というビルドですが、PipelineビルドはJenkinsで実行する、という少し性格の異なるビルドになっています。
PipelineビルドもJenkinsfileがあるGit URLをoc new-app
で渡すことができますが、Dockerfileのように埋め込むこともできます。個人的にはテスト目的での使用が多いので、埋め込みスタイルを多用しています。
oc new-build
には--dockerfile相当の--jenkinsfileのようなオプションは実装されていないので、Jenkinsfine埋め込みyamlを直接ぶち込みます。
$ cat <<EOF | oc create -f - kind: BuildConfig apiVersion: v1 metadata: name: test-pipeline labels: name: test-pipeline spec: strategy: type: JenkinsPipeline jenkinsPipelineStrategy: jenkinsfile: |- pipeline { agent { label 'maven' } stages { stage('Stage 1') { steps { sh "echo Stage 1" } } stage('Stage 2') { steps { sh "echo Stage 2" } } } } EOF
pipeline、旧syntaxではnode('maven') { sh "echo test" }
で大丈夫なのですが、新しいsyntaxになってからブロックのネストがいっぱいになってちょっと冗長な雰囲気になりました。
例では"echo Stage 1"などの実行しかしていませんが、別のビルドを実行したりイメージを別環境にリリースしたり、統合テストをキックしたりなど好きなことができます。いろいろやっている例が https://blog.openshift.com/building-declarative-pipelines-openshift-dsl-plugin/ に掲載されています。
Pipelineビルドを作成すると、実行のためのJenkinsが自動でデプロイされます。
$ oc get all NAME TYPE FROM LATEST buildconfigs/test-pipeline JenkinsPipeline 0 NAME REVISION DESIRED CURRENT TRIGGERED BY deploymentconfigs/jenkins 1 1 1 config,image(jenkins:latest) NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD routes/jenkins jenkins-test-jenkins.192.168.42.143.nip.io jenkins <all> edge/Redirect None NAME READY STATUS RESTARTS AGE po/jenkins-1-dl7tq 1/1 Running 0 4m NAME DESIRED CURRENT READY AGE rc/jenkins-1 1 1 1 4m NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/jenkins 172.30.211.203 <none> 80/TCP 4m svc/jenkins-jnlp 172.30.28.12 <none> 50000/TCP 4m $ oc start-build test-pipeline
Jenkinsのログをみると、agent指定されているのでagentとなる新しいPodをスケジューリングして実行しているのがわかります。
$ oc logs dc/jenkins Dec 08, 2017 9:37:57 AM io.fabric8.jenkins.openshiftsync.BuildConfigWatcher updateJob INFO: Updated job test-jenkins-test-pipeline from BuildConfig NamespaceName{test-jenkins:test-pipeline} with revision: 111669 Dec 08, 2017 9:37:57 AM io.fabric8.jenkins.openshiftsync.BuildSyncRunListener onStarted INFO: starting polling build job/test-jenkins-test-pipeline/1/ Dec 08, 2017 9:38:01 AM org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader$4$1 load WARNING: took 334ms to load/not load jenkins.model.Class from classLoader hudson.PluginManager$UberClassLoader Dec 08, 2017 9:38:16 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud provision INFO: Excess workload after pending Spot instances: 1 Dec 08, 2017 9:38:16 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud provision INFO: Template: Kubernetes Pod Template Dec 08, 2017 9:38:17 AM okhttp3.internal.platform.Platform log INFO: ALPN callback dropped: HTTP/2 is disabled. Is alpn-boot on the boot class path? Dec 08, 2017 9:38:17 AM hudson.slaves.NodeProvisioner$StandardStrategyImpl apply INFO: Started provisioning Kubernetes Pod Template from openshift with 1 executors. Remaining excess workload: 0 Dec 08, 2017 9:38:18 AM okhttp3.internal.platform.Platform log INFO: ALPN callback dropped: HTTP/2 is disabled. Is alpn-boot on the boot class path? Dec 08, 2017 9:38:18 AM org.csanchez.jenkins.plugins.kubernetes.ProvisioningCallback call INFO: Created Pod: maven-vb87g in namespace test-jenkins Dec 08, 2017 9:38:18 AM org.csanchez.jenkins.plugins.kubernetes.ProvisioningCallback call INFO: Waiting for Pod to be scheduled (0/100): maven-vb87g Dec 08, 2017 9:38:24 AM okhttp3.internal.platform.Platform log INFO: ALPN callback dropped: HTTP/2 is disabled. Is alpn-boot on the boot class path? Dec 08, 2017 9:38:24 AM org.csanchez.jenkins.plugins.kubernetes.ProvisioningCallback call INFO: Container is waiting maven-vb87g [jnlp]: ContainerStateWaiting(message=null, reason=ContainerCreating, additionalProperties={}) Dec 08, 2017 9:38:24 AM org.csanchez.jenkins.plugins.kubernetes.ProvisioningCallback call INFO: Waiting for Pod to be scheduled (1/100): maven-vb87g
このPod maven-vb87g
の中で指定したステップが実行されます。
Pipelineビルドの状況はWebコンソールから確認でき、View Logを押すとJenkinsの画面に遷移してログを確認できます。
次は'maven'となっている部分の説明とカスタマイズについて書く予定です。
OpenShiftでPVの中身を別のPVへ移行する
OpenShift 全部俺 Advent Calendar 2017
OpenShiftやKubernetesでPVを作って使ってたらPVが一杯になってしまったので大きなサイズのPVへ移行したい、であるとか、HDDのPVを使ってたけどSSDのPVに変えよう、というようなデータ移行のユースケースが発生します。
OpenShiftのdocker-reigstyのPVを移行してみましょう。
oc project default ### 現在のPVC名とボリューム名の確認 (この例では registry と registry-storage) oc get pvc ### docker-registryを一旦停止 oc scale dc docker-registry --replicas=0 ### データ移行に利用するno-opコンテナを起動 oc run sleep --image=registry.access.redhat.com/rhel7 -- tail -f /dev/null ### 現在のPVCをno-opコンテナにマウント oc volume dc/sleep --add -t pvc --name=registry --claim-name=registry --mount-path=/old-registry ### 新しいPV/PVCをno-opコンテナにマウント(dynamic provisioning前提、dynamic provisioningがないならPVを事前に設定) oc volume dc/sleep --add -t pvc --name=new-registry --claim-name=new-registry --mount-path=/new-registry --claim-mode=ReadWriteMany --claim-size=400Gi ### no-opコンテナにrsh oc rsh sleep-X-XXXXX ### no-opコンテナ上でデータをrsyncで移行 rsync -avxHAX --progress /old-registry /new-registry ### docker-registryを現在のPVから新しいPVへスイッチ oc volume dc/docker-registry --remove --name=registry-storage --confirm oc volume dc/docker-registry --add -t pvc --name=registry-storage --claim-name=new-registry --mount-path=/registry ### docker-registryを再開 oc scale dc docker-registry --replicas=1
問題なければ古いPVCは消して良いでしょう。
KubernetesだとOpenShiftのoc volumeのようなコマンドが無いと思いますが、新PVCとデータ移行Podをapplyして同じ作業をすれば良いはずです。
他にkubectl cpでデータ吸い出してPV/PVC切り替えて新しいPodに書き戻す、という安直なアプローチもありますが、アプリが動いたままで書き込み途中のデータを吸い出してしまったり、バックアップ後に書き込まれたデータがロストしたり、新しいPodがデータを上書きされる想定ではないので誤動作する、などの可能性があるので注意しましょう。
OpenShiftでDockerfileやバイナリビルド利用してコンテナをビルドする
OpenShift 全部俺 Advent Calendar 2017
昨日はギョウザパーティでした。基本のs2iビルドではソースコードからビルドしましたが、今回はDockerfileを利用します。
ソースコードと同じようにDockerfileが置いてあるGit URLを指定すると同じようにビルドできるのですが、それでは面白くないのでちょっとアドホックなビルドをしてみましょう。
tail -f /dev/null
を実行するコンテナイメージを作成するDockerfileをGitを利用せずにOpenShiftに食べさせてみます。oc new-build
でビルドしてからoc new-app
でImageStreamを指定してアプリケーションを作成という流れになります。
oc new-project test-dockerbuild cat <<EOF > Dockerfile FROM registry.access.redhat.com/rhel CMD tail -f /dev/null EOF cat Dockerfile | oc new-build --dockerfile=- --to=sleep oc logs sleep-1-build -f oc new-app sleep
できました。デプロイされたコンテナを見ると実行されていますね。
$ oc rsh dc/sleep ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 1000080+ 1 0.0 0.0 4352 352 ? Ss 06:34 0:00 tail -f /dev/nu 1000080+ 16 0.0 0.0 47448 1612 ? Rs+ 06:35 0:00 ps aux
この方式だとDockerfileはBuildConfigに埋め込まれているので、以降内容を編集する場合はoc edit bc
で直接編集できます。
$ oc export bc sleep kind: BuildConfig spec: source: dockerfile: | FROM registry.access.redhat.com/rhel CMD tail -f /dev/null type: Dockerfile
ただし、上記のDockerfile埋め込みだとビルドコンテキストが渡せないので、ファイルをイメージ内にコピーしたりしたいときに困ります。そのような場合はバイナリビルドにしてoc start-build
時にディレクトリをまるごと転送する、というのもできます。
oc new-build --strategy=docker --binary=true --name=$APP_NAME oc start-build $APP_NAME --from-dir=. oc new-app $APP_NAME
バイナリビルドはDockerfileに限らず、s2iのソースツリーでも同じようにGitを経由しないビルドができます。
ちなみにDockerfileを利用したビルドは現状docker daemon内、つまりrootで実行されているためセキュリティレベルとしては最低です。このため、OpenShift OnlineではDockerビルドは無効化されています。そのうちbuildahなどを利用してdocker daemonとは無関係の通常権限でのDockerfileビルドもできるようになるとは思いますが、そこまでしてDockerfile形式を利用しなければならない理由もあまり無いので、より扱いやすいコンテナイメージの記述およびビルド方式が先にサポートされる気もします。
OpenShift Container Platform 3.7をシングルノードでインストールする
OpenShift 全部俺 Advent Calendar 2017
商用版のOpenShift Container Platform 3.7をシングルノードでインストールしてみます。
利用する/etc/ansible/hosts
ファイルの中身はこんな感じです。OpenShift Container Platform 3.6以前ではシングルマスター構成ではmaster-api, master-controllers, etcdが全部一つのプロセスmasterで動作する構成でしたが、管理性向上のため3.7ではこれは廃止され、マルチマスターと同一のプロセス構成になりました。
[OSEv3:children] masters etcd nodes [OSEv3:vars] ansible_ssh_user=nekop ansible_become=true deployment_type=openshift-enterprise openshift_master_identity_providers=[{'name': 'allow_all', 'login': 'true', 'challenge': 'true', 'kind': 'AllowAllPasswordIdentityProvider'}] os_sdn_network_plugin_name=redhat/openshift-ovs-multitenant openshift_node_kubelet_args={'kube-reserved': ['cpu=100m,memory=100Mi'], 'system-reserved': ['cpu=100m,memory=100Mi'], 'eviction-hard': [ 'memory.available<4%', 'nodefs.available<4%', 'nodefs.inodesFree<4%', 'imagefs.available<4%', 'imagefs.inodesFree<4%' ], 'eviction-soft': [ 'memory.available<8%', 'nodefs.available<8%', 'nodefs.inodesFree<8%', 'imagefs.available<8%', 'imagefs.inodesFree<8%' ], 'eviction-soft-grace-period': [ 'memory.available=1m30s', 'nodefs.available=1m30s', 'nodefs.inodesFree=1m30s', 'imagefs.available=1m30s', 'imagefs.inodesFree=1m30s' ]} openshift_disable_check=memory_availability,disk_availability openshift_master_default_subdomain=apps.example.com [masters] s37.example.com [etcd] s37.example.com [nodes] s37.example.com openshift_node_labels="{'region': 'infra'}" openshift_schedulable=true
rootでssh-copy-idしてあるstatic IPを持つRHEL 7.4 VMからスタートし、インストールの事前準備はこんな感じで流しています。dockerのstorage driverはoverlay2を指定します。
HOSTNAME=s37.example.com RHSM_USERNAME= RHSM_PASSWORD= RHSM_POOLID= OPENSHIFT_VERSION=3.7 hostnamectl set-hostname $HOSTNAME timedatectl set-timezone Asia/Tokyo adduser -G wheel nekop cat << EOM > /etc/sudoers.d/wheel %wheel ALL=(ALL) NOPASSWD: ALL Defaults:%wheel !requiretty EOM mkdir /home/nekop/.ssh/ cp -a /root/.ssh/authorized_keys /home/nekop/.ssh/ chown nekop.nekop -R /home/nekop/.ssh/ subscription-manager register --username=$RHSM_USERNAME --password=$RHSM_PASSWORD subscription-manager attach --pool $RHSM_POOLID subscription-manager repos --disable=* subscription-manager repos \ --enable=rhel-7-server-rpms \ --enable=rhel-7-server-extras-rpms \ --enable=rhel-7-server-optional-rpms \ --enable=rhel-7-server-rh-common-rpms \ --enable=rhel-7-fast-datapath-rpms \ --enable=rhel-7-server-ose-$OPENSHIFT_VERSION-rpms yum update -y yum install chrony wget git net-tools bind-utils iptables-services bridge-utils nfs-utils sos sysstat bash-completion lsof tcpdump yum-utils yum-cron docker atomic-openshift-utils -y sed -i 's/DOCKER_STORAGE_OPTIONS=/DOCKER_STORAGE_OPTIONS="--storage-driver overlay2"/' /etc/sysconfig/docker-storage systemctl enable chronyd docker reboot
これでインストールの準備が整ったので、ログインしなおした後にssh keyを用意してssh-copy-idしてansibleします。問題なければ再度確認も兼ねて一応rebootするようにしています。
ssh nekop@s37.example.com ssh-keygen ssh-copy-id s37.example.com vi /etc/ansible/hosts ansible-playbook -vvvv /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml | tee -a openshift-install-$(date +%Y%m%d%H%M%S).log reboot
マルチノードの場合はglusterも一緒にセットアップできるのでglusterでPVを使えるようにするのがラクなんですが、シングルノードなのでhostPath
でPVを作成しておきます。SELinuxでコンテナからのアクセスを許可するのにchconでsvirt_sandbox_file_t
を設定します。
COUNT=100 sudo mkdir -p /var/lib/origin/openshift.local.pv/ for i in $(seq 1 $COUNT); do PVNAME=pv$(printf %04d $i) sudo mkdir -p /var/lib/origin/openshift.local.pv/$PVNAME cat <<EOF | oc create -f - apiVersion: v1 kind: PersistentVolume metadata: name: $PVNAME spec: accessModes: - ReadWriteOnce - ReadWriteMany - ReadOnlyMany capacity: storage: 100Gi persistentVolumeReclaimPolicy: Retain hostPath: path: /var/lib/origin/openshift.local.pv/$PVNAME EOF done sudo chcon -R -t svirt_sandbox_file_t /var/lib/origin/openshift.local.pv/ sudo chmod -R 777 /var/lib/origin/openshift.local.pv/
Reference
Red Hat OpenShift Application Runtimes
OpenShift 全部俺 Advent Calendar 2017
Red Hat OpenShift Application Runtimesがリリースされたのでさわってみたいと思います。Spring BootやVert.x, WildFly Swarmなどを使ってOpenShift上でマイクロサービスアプリケーションの開発をサポートする製品です。
https://launch.openshift.io/ というサイトでプロジェクトのひな型が作成できるので、まずはそれを利用してWildFly Swarmのプロジェクトを見てみましょう。
生成されたプロジェクトはローカル開発とOpenShiftを利用した開発の両方に対応するfabric8を活用したプロジェクトのようです。oc get all
を見てみると、Binaryビルドなので、ソースからOpenShift側でビルドされるのではなく、ローカルでビルドしたwarファイルを転送してコンテナイメージをビルドしている構成です。
$ mvn clean fabric8:deploy (長いので省略) $ oc get all NAME TYPE FROM LATEST buildconfigs/booster-crud-wildfly-swarm-s2i Source Binary 1 NAME TYPE FROM STATUS STARTED DURATION builds/booster-crud-wildfly-swarm-s2i-1 Source Binary Complete 2 minutes ago 2m3s NAME DOCKER REPO TAGS UPDATED imagestreams/booster-crud-wildfly-swarm 172.30.1.1:5000/test-rhoar/booster-crud-wildfly-swarm latest 50 seconds ago NAME REVISION DESIRED CURRENT TRIGGERED BY deploymentconfigs/booster-crud-wildfly-swarm 1 1 1 config,image(booster-crud-wildfly-swarm:latest) NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD routes/booster-crud-wildfly-swarm booster-crud-wildfly-swarm-test-rhoar.192.168.42.143.nip.io booster-crud-wildfly-swarm 8080 None NAME READY STATUS RESTARTS AGE po/booster-crud-wildfly-swarm-1-deploy 1/1 Running 0 18s po/booster-crud-wildfly-swarm-1-fgdj8 0/1 Running 0 15s po/booster-crud-wildfly-swarm-s2i-1-build 0/1 Completed 0 2m NAME DESIRED CURRENT READY AGE rc/booster-crud-wildfly-swarm-1 1 1 0 18s NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/booster-crud-wildfly-swarm 172.30.79.11 <none> 8080/TCP 20s
BuildConfigを見ると利用イメージがregistry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift
になっているので、これを使えば手元でビルドしてバイナリ転送ではなく、OpenShift側でソースからビルド(s2iビルド)でも大丈夫でしょう。
というわけでRHOARを利用した最小のSwarmプロジェクト https://github.com/nekop/hello-swarm を作ってみました。
$ oc new-project test-swarm $ oc new-app registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift~https://github.com/nekop/hello-swarm $ oc expose svc hello-swarm $ curl hello-swarm-test-rhoar.192.168.42.143.nip.io hello world