DNS 解決とホストエイリアスの必要性
Kubernetes クラスター内で構築されたアプリケーションが、社内向けのサービス(Git、Nexus、Nacos など)へ依存している場合、それらのドメイン名がパブリック DNS に登録されていないことが一般的です。この場合、Pod からはこれらのエンドポイントへの接続が不可能になります。
この問題を解決するためには、各 Pod のコンテナイメージに含まれる `/etc/hosts` ファイルに手動で IP アドレスとドメインのマッピングを追加する必要があります。Kubernetes においては、Deployment マニフェストの `spec.template.spec.hostAliases` フィールドを使用することで、これが自動的に実行されます。
RBAC 権限設定
Jenkins や CI/CD ツールとして動作する Pod がクラスター内の他のポッドやログ、シークレットにアクセスするには、適切なロールベースのアクセス制御(RBAC)設定が必要です。以下は、ServiceAccount とそれに紐づく Role、RoleBinding の定義例です。
apiVersion: v1
kind: ServiceAccount
metadata:
name: pipeline-agent
namespace: production-env
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-manager
namespace: production-env
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-binding
namespace: production-env
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-manager
subjects:
- kind: ServiceAccount
name: pipeline-agent
namespace: production-env
永続ストレージの準備
CI ツールの設定情報やビルド成果物を保持するために、NFS プロトコルを使用した永続ボリュームが必要です。PersistentVolume(PV) と PersistentVolumeClaim(PVC) を定義します。
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-storage
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.10.50
path: /srv/shared/jenkins-workspace
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: app-claim
namespace: production-env
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
アプリケーションデプロイメントとホストエイリアス
ここが重要な箇所です。`hostAliases` セクションで内部ネットワークの IP とドメイン名を指定し、Pod 起動時に `/etc/hosts` に書き込みます。また、セキュリティコンテキストやリソース制限も適切に設定しています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: build-service
namespace: production-env
spec:
selector:
matchLabels:
app: build-service
template:
metadata:
labels:
app: build-service
spec:
serviceAccountName: pipeline-agent
terminationGracePeriodSeconds: 30
# ポッド内部の /etc/hosts にエントリを追加
hostAliases:
- ip: "192.168.10.60"
hostnames:
- "git.internal.local"
- "maven.internal.local"
- "docker-registry.internal.local"
- "nexus.internal.local"
containers:
- name: build-tool
image: jenkins/jenkins:lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 50000
name: agent-port
protocol: TCP
env:
- name: JAVA_OPTS
value: "-Xmx5g -Duser.timezone=Asia/Tokyo"
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 90
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
volumeMounts:
- name: workspace
mountPath: /var/jenkins_home
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
securityContext:
fsGroup: 1000
volumes:
- name: workspace
persistentVolumeClaim:
claimName: app-claim
Ingress リソースによる外部公開
定義したデプロイメントを外部からアクセス可能にするために、nginx インゲレスコントローラー向けにルールを設定します。古い API バージョンではなく、最新の networking.k8s.io/v1 を使用する推奨構成です。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: build-access
namespace: production-env
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "2g"
nginx.ingress.kubernetes.io/proxy-read-timeout: "900"
nginx.ingress.kubernetes.io/proxy-send-timeout: "900"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: "build-platform.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: build-service
port:
number: 8080