オンプレミスでCircleCI Serverを動かすシリーズの第2回です。前回は必要となるツールをインストールしました。今回はこれらのツールを使い、CircleCIサーバーを動かすためのEKSクラスター、アーティファクトを保存するS3バケット、アーティファクトをセキュアに保存するために必要な署名キーなどを作っていきます。
EKSクラスターの作成
eksctlコマンドでEKSクラスターを作成します。まず以下の内容でcircleci-eks.yml
というクラスターの設定をまとめたファイルを作成します。
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: circleci-server region: ap-northeast-1 version: '1.21' iam: withOIDC: true serviceAccounts: - metadata: name: aws-load-balancer-controller namespace: kube-system wellKnownPolicies: awsLoadBalancerController: true - metadata: name: external-dns namespace: kube-system wellKnownPolicies: externalDNS: true vpc: cidr: 10.21.0.0/16 nat: gateway: Single addons: - name: vpc-cni - name: coredns - name: kube-proxy managedNodeGroups: - name: ng-1 instanceType: t3.xlarge desiredCapacity: 3 minSize: 1 maxSize: 3 volumeSize: 20 privateNetworking: true iam: attachPolicyARNs: - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
上記ファイルの内容を具体的に解説すると
circleci-server
という名前でバージョン1.21のクラスターを作成する- vpc-cni/coredns/kube-proxyをクラスターアドオンとしてデプロイする
- ノードグループにt3.xlargeのEC2インスタンスを3台起動する
- AWS Load Balancer Controller/ExternalDNS用のサービスアカウントを作成する
となっています。公式ドキュメントではm5.xlargeを4台起動しているのですが、あくまでテストということで、少し安価な設定としています。またAWS Load Balancer ControllerやExternalDNSは必須ではないものの、一般的なEKSクラスターを動かす際にはあると便利ですので、使い回しができるよう設定に含めています。
設定ファイルが準備できたら、以下のコマンドでクラスターを作成します。この作業は完了まで30分程度の時間がかかります。
$ eksctl create cluster -f circleci-eks.yml
AWS Load Balancer Controllerのデプロイ
クラスターが完成したら、以下のコマンドでHelmのリポジトリを追加し、AWS Load Balancer Controllerをデプロイします。
$ helm repo add eks https://aws.github.io/eks-charts $ helm repo update $ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ --namespace kube-system \ --set clusterName=circleci-server \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller \ --set enableCertManager=false
ExternalDNSのデプロイ
前述のAWS L-B-Cと同様に、以下のコマンドでクラスターにExternalDNSをデプロイします。domainFiltersには使用するドメイン名(example.comなど)を、リスト形式で指定してください。txtOwnerIdは、追加したDNSレコードを他のExternalDNSに上書きされないよう、レコードのオーナーを識別するためのラベルです。ExternalDNSごとにユニークな文字列を指定してください。今回は競合するExternalDNSが存在しない前提ですので、circleci-server
のような文字列でよいでしょう。
$ helm repo add external-dns https://kubernetes-sigs.github.io/external-dns $ helm repo update $ helm install external-dns external-dns/external-dns \ --namespace kube-system \ --set serviceAccount.create=false \ --set serviceAccount.name=external-dns \ --set sources=\{service,ingress\} \ --set domainFilters=\{(ドメイン名)\} \ --set policy=sync \ --set provider=aws \ --set txtOwnerId=(任意の文字列)
S3バケットの作成
アーティファクトやテスト結果などを保存するS3バケットを作成します。ここではvtj-circleci-server
という名前のバケットを作成しています。
$ aws s3api create-bucket \ --bucket vtj-circleci-server \ --region ap-northeast-1 \ --create-bucket-configuration LocationConstraint=ap-northeast-1
続いて、CircleCI ServerがS3への書き込みに利用するIAMユーザーを作成します。ここではcircleci-server
というユーザーを作成しています。
$ aws iam create-user --user-name circleci-server
このユーザーにアタッチするポリシードキュメントを作成します。以下の内容でpolicy.json
というファイルを作成してください。なおResourceに指定しているバケット名(2箇所のvtj-circleci-server
の部分)は、先ほど作成したバケット名に書き換えてください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutAnalyticsConfiguration", "s3:GetObjectVersionTagging", "s3:CreateBucket", "s3:GetObjectAcl", "s3:GetBucketObjectLockConfiguration", "s3:DeleteBucketWebsite", "s3:PutLifecycleConfiguration", "s3:GetObjectVersionAcl", "s3:PutObjectTagging", "s3:DeleteObject", "s3:DeleteObjectTagging", "s3:GetBucketPolicyStatus", "s3:GetObjectRetention", "s3:GetBucketWebsite", "s3:GetJobTagging", "s3:DeleteObjectVersionTagging", "s3:PutObjectLegalHold", "s3:GetObjectLegalHold", "s3:GetBucketNotification", "s3:PutBucketCORS", "s3:GetReplicationConfiguration", "s3:ListMultipartUploadParts", "s3:PutObject", "s3:GetObject", "s3:PutBucketNotification", "s3:DescribeJob", "s3:PutBucketLogging", "s3:GetAnalyticsConfiguration", "s3:PutBucketObjectLockConfiguration", "s3:GetObjectVersionForReplication", "s3:GetLifecycleConfiguration", "s3:GetInventoryConfiguration", "s3:GetBucketTagging", "s3:PutAccelerateConfiguration", "s3:DeleteObjectVersion", "s3:GetBucketLogging", "s3:ListBucketVersions", "s3:ReplicateTags", "s3:RestoreObject", "s3:ListBucket", "s3:GetAccelerateConfiguration", "s3:GetBucketPolicy", "s3:PutEncryptionConfiguration", "s3:GetEncryptionConfiguration", "s3:GetObjectVersionTorrent", "s3:AbortMultipartUpload", "s3:PutBucketTagging", "s3:GetBucketRequestPayment", "s3:GetAccessPointPolicyStatus", "s3:GetObjectTagging", "s3:GetMetricsConfiguration", "s3:PutBucketVersioning", "s3:GetBucketPublicAccessBlock", "s3:ListBucketMultipartUploads", "s3:PutMetricsConfiguration", "s3:PutObjectVersionTagging", "s3:GetBucketVersioning", "s3:GetBucketAcl", "s3:PutInventoryConfiguration", "s3:GetObjectTorrent", "s3:PutBucketWebsite", "s3:PutBucketRequestPayment", "s3:PutObjectRetention", "s3:GetBucketCORS", "s3:GetBucketLocation", "s3:GetAccessPointPolicy", "s3:GetObjectVersion", "s3:GetAccessPoint", "s3:GetAccountPublicAccessBlock", "s3:ListAllMyBuckets", "s3:ListAccessPoints", "s3:ListJobs" ], "Resource": [ "arn:aws:s3:::vtj-circleci-server", "arn:aws:s3:::vtj-circleci-server/*" ] } ] }
ポリシーをユーザーにアタッチします。
$ aws iam put-user-policy \ --user-name circleci-server \ --policy-name circleci-server \ --policy-document file://policy.json
最後に、IAMユーザーのアクセスキーを作成します。以下のコマンドを実行し、出力されたアクセスキーとシークレットキーを控えておいてください。
$ aws iam create-access-key --user-name circleci-server { "AccessKey": { "UserName": "circleci-server", "AccessKeyId": "アクセスキー", "Status": "Active", "SecretAccessKey": "シークレットキー", "CreateDate": "2022-04-18T08:38:48+00:00" } }
署名キーの作成
CircleCIが生成するアーティファクトをセキュアに保存するためには、暗号化キーと署名キーが必要になります。これらのキーセットを生成しましょう。これらはCircleCIが提供しているserver-keysetsというDockerイメージを使うことで、簡単に生成することが可能です。
まず作業用のUbuntuマシンにDockerをインストールします。パッケージ名がdocker.io
である点に注意してください。docker
パッケージはまったく別のアプリケーションです。
$ sudo apt install docker.io
アーティファクト署名キー生成するには、以下のコマンドを実行します。
$ sudo docker run --rm circleci/server-keysets:latest generate signing -a stdout {:meta {"name" "signing", "purpose" "SIGN_AND_VERIFY", "type" "HMAC_SHA1", "versions" [{"exportable" false, "status" "PRIMARY", "versionNumber" 1}], "encrypted" false}, :keys {1 {"hmacKeyString" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "size" 256}}}
暗号化キー生成するには、以下のコマンドを実行します。
$ sudo docker run --rm circleci/server-keysets:latest generate encryption -a stdout {:meta {"name" "encryption", "purpose" "DECRYPT_AND_ENCRYPT", "type" "AES", "versions" [{"exportable" false, "status" "PRIMARY", "versionNumber" 1}], "encrypted" false}, :keys {1 {"aesKeyString" "xxxxxxxxxxxxxxx", "hmacKey" {"hmacKeyString" "xxxxxxxxxxxxxxxxxxxxxxxxxxx", "size" 256}, "mode" "CBC", "size" 128}}}
出力された文字列を、安全な場所に控えておいてください。もしキーを失ってしまうと、暗号化されたアーティファクトを取り出せなくなる可能性があります。なお勘違いしやすいのですが、KeyString
に含まれる内容だけではなく、{:meta
から最後の閉じ括弧までの全体が必要となります。注意してください。
GitHub OAuthアプリの作成
CircleCI ServerはVCSと連携して動作するのが前提です。そこでGitHubと連携するため、GitHub側にOAuthアプリを作成します。
GitHubにログインしたら、アプリを追加したいOrganizationないしは個人のSettingsを開きます。左ペインから「Developer settings」→「OAuth Apps」と辿り、Register an application
をクリックしてください。
新規OAuthアプリの設定画面が開きます。「アプリ名」「URL」「callback URL」を入力してください。アプリ名はわかりやすい名前なら何でも構いません。CircleCI
などとしておきましょう。URLはCircleCI Serverをホストする予定のFQDNとなります(例: https://circleci.example.com)。https://
から記述する必要がある点に注意してください。callback URLは、URLの末尾に/auth/github
を足したものになります。入力できたらRegister application
をクリックしてください。
OAuthアプリの作成が完了すると、クライアントIDが発行されます。これを控えておいてください。そしてGenerate a new client secret
をクリックして、クライアントシークレットを生成します。
クライアントシークレットが生成されたら、こちらも控えておきます。
以上で必要な準備は完了です。次回はいよいよ、CircleCI Serverのコアサービスをインストールしていきます。