Pod Affinity と Anti-Affinity
Podは特定のノードや特定の状況下で実行されるよう制約をかけることができます。これには、ノードごとに1つのアプリケーションPodのみを実行したい場合や、複数のPodをノード上でペアリングしたい場合などが含まれます。さらに、ノードアフィニティを使用する場合、Podには優先的または必須の制約を設定できます。
このレッスンでは、checkout-redis Podをノードごとに1つのインスタンスのみ実行するようにし、checkout Podをcheckout-redis Podが存在するノードにのみ1つのインスタンスを実行するように、Pod間のアフィニティとアンチアフィニティに焦点を当てます。これにより、キャッシングPod(checkout-redis)が最高のパフォーマンスを得るためにcheckout Podインスタンスとローカルで実行されるようにな ります。
まず最初に、checkoutとcheckout-redis Podが実行されていることを確認しましょう:
NAME READY STATUS RESTARTS AGE
checkout-698856df4d-vzkzw 1/1 Running 0 125m
checkout-redis-6cfd7d8787-kxs8r 1/1 Running 0 127m
両方のアプリケーションがクラスター内で1つのPodを実行していることがわかります。次に、それらがどこで実行されているかを確認しましょう:
checkout-698856df4d-vzkzw ip-10-42-11-142.us-west-2.compute.internal
checkout-redis-6cfd7d8787-kxs8r ip-10-42-10-225.us-west-2.compute.internal
上記の結果から、checkout-698856df4d-vzkzw Podはip-10-42-11-142.us-west-2.compute.internalノードで実行され、checkout-redis-6cfd7d8787-kxs8r Podはip-10-42-10-225.us-west-2.compute.internalノードで実行されていることがわかります。
あなたの環境では、最初にPodが同じノード上で実行されている場合があります
checkoutデプロイメントにpodAffinityとpodAntiAffinityポリシーを設定して、ノードごとに1つのcheckout Podが実行され、checkout-redis Podが既に実行されているノードでのみ実行されるようにしましょう。優先的な動作ではなく要件とするためにrequiredDuringSchedulingIgnoredDuringExecutionを使用します。
次のKustomizationはcheckoutデプロイメントにpodAffinityとpodAntiAffinityポリシーの両方を指定したaffinityセクションを追加します:
- Kustomize Patch
- Deployment/checkout
- Diff
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout
namespace: checkout
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- service
- key: app.kubernetes.io/instance
operator: In
values:
- checkout
topologyKey: kubernetes.io/hostname
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/type: app
name: checkout
namespace: checkout
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: service
app.kubernetes.io/instance: checkout
app.kubernetes.io/name: checkout
template:
metadata:
annotations:
prometheus.io/path: /metrics
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/component: service
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/instance: checkout
app.kubernetes.io/name: checkout
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- service
- key: app.kubernetes.io/instance
operator: In
values:
- checkout
topologyKey: kubernetes.io/hostname
containers:
- envFrom:
- configMapRef:
name: checkout
image: public.ecr.aws/aws-containers/retail-store-sample-checkout:1.2.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 3
name: checkout
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
limits:
memory: 512Mi
requests:
cpu: 250m
memory: 512Mi
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
fsGroup: 1000
serviceAccountName: checkout
volumes:
- emptyDir:
medium: Memory
name: tmp-volume