自定义Gateway Controller其实应该是一个很常见的需求,但在网上缺很难找到可以step by step完成的例子。StackOverflow的这个回答给出了很好的思路,通过helm template
生成yaml,在此基础上微调,然后使用kubectl apply
创建。
基于helm默认安装选项生成的gateway controller,包含以下内容:
- 创建一个有读取secret权限的ServiceAccount。
- 以#1创建的account运行一个Pod,里面包含一个以router方式(而不是sidecar)运行的Envoy。
- 创建一个LoadBalancer类型的Service,把#2创建的Pod向外暴露。
- 为#3创建Deploy和Scale相关的策略。
需要注意的地方有:
- Deployment的template需要关闭sidecar的自动注入。
apiVersion: apps/v1
kind: Deployment
spec:
template:
annotations:
sidecar.istio.io/inject: "false"
- 如果gateway controller不是创建在istio-system namespace下,istio-proxy的启动参数,zipkin和istio-pilot后面要加上.istio-system。
args:
- --zipkinAddress
- zipkin.istio-system:9411
- --discoveryAddress
- istio-pilot.istio-system:15010
- 本例并没有打开tls,如果需要,要注意调整需要挂载的secret的名字:
volumes:
- name: istio-certs
secret:
secretName: istio.istio-ingressgateway-service-account
- name: ingressgateway-certs
secret:
secretName: "istio-ingressgateway-certs"
- name: ingressgateway-ca-certs
secret:
secretName: "istio-ingressgateway-ca-certs"
下面贴出生成的yaml文件,以供参考。
# RABC
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-ingressgateway-service-account
namespace: default
labels:
app: my-ingressgateway
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-ingressgateway-sds
namespace: default
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-ingressgateway-sds
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: my-ingressgateway-sds
subjects:
- kind: ServiceAccount
name: my-ingressgateway-service-account
# Service
---
apiVersion: v1
kind: Service
metadata:
name: my-ingressgateway
namespace: default
labels:
app: my-ingressgateway
istio: my-ingressgateway
spec:
type: LoadBalancer
selector:
app: my-ingressgateway
istio: my-ingressgateway
ports:
-
name: http2
port: 80
targetPort: 80
# Deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-ingressgateway
namespace: default
labels:
app: my-ingressgateway
istio: my-ingressgateway
spec:
selector:
matchLabels:
app: my-ingressgateway
istio: my-ingressgateway
template:
metadata:
labels:
app: my-ingressgateway
istio: my-ingressgateway
annotations:
sidecar.istio.io/inject: "false"
spec:
serviceAccountName: my-ingressgateway-service-account
containers:
- name: istio-proxy
image: "docker.io/istio/proxyv2:1.2.0"
imagePullPolicy: IfNotPresent
ports:
# healthcheck
- containerPort: 15020
# web
- containerPort: 80
- containerPort: 443
# This port is used for testdata.
- containerPort: 31400
args:
- proxy
- router
- --domain
- $(POD_NAMESPACE).svc.cluster.local
- --log_output_level=default:info
- --drainDuration
- '45s'
- --parentShutdownDuration
- '1m0s'
- --connectTimeout
- '10s'
- --serviceCluster
- my-ingressgateway
- --zipkinAddress
- zipkin.istio-system:9411
- --proxyAdminPort
- "15000"
- --statusPort
- "15020"
- --controlPlaneAuthPolicy
- NONE
- --discoveryAddress
- istio-pilot.istio-system:15010
readinessProbe:
failureThreshold: 30
httpGet:
path: /healthz/ready
port: 15020
scheme: HTTP
initialDelaySeconds: 1
periodSeconds: 2
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 100m
memory: 128Mi
env:
- name: NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: HOST_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: ISTIO_META_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: ISTIO_META_CONFIG_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: ISTIO_META_ROUTER_MODE
value: sni-dnat
volumeMounts:
- name: istio-certs
mountPath: /etc/certs
readOnly: true
- name: ingressgateway-certs
mountPath: "/etc/istio/ingressgateway-certs"
readOnly: true
- name: ingressgateway-ca-certs
mountPath: "/etc/istio/ingressgateway-ca-certs"
readOnly: true
volumes:
- name: istio-certs
secret:
secretName: istio.istio-ingressgateway-service-account
optional: true
- name: ingressgateway-certs
secret:
secretName: "istio-ingressgateway-certs"
optional: true
- name: ingressgateway-ca-certs
secret:
secretName: "istio-ingressgateway-ca-certs"
optional: true
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64
- ppc64le
- s390x
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 2
preference:
matchExpressions:
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64
- weight: 2
preference:
matchExpressions:
- key: beta.kubernetes.io/arch
operator: In
values:
- ppc64le
- weight: 2
preference:
matchExpressions:
- key: beta.kubernetes.io/arch
operator: In
values:
- s390x
# Deploy & Scale Policy
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: my-ingressgateway
namespace: default
labels:
app: my-ingressgateway
istio: my-ingressgateway
spec:
maxReplicas: 3
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-ingressgateway
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 80
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: my-ingressgateway
namespace: default
labels:
app: my-ingressgateway
istio: my-ingressgateway
spec:
minAvailable: 1
selector:
matchLabels:
app: my-ingressgateway
istio: my-ingressgateway