简介
APISIX 是动态、实时、高性能的 API 网关。它提供丰富的流量管理功能,比如负载均衡、动态上游、金丝雀发布、熔断、认证、可观测性等。既可以使用 APISIX API 网关处理传统的南北向流量,也可以使用它处理服务间的东西向流量。同时,它也可被用作 Kubernetes Ingress 控制器。
APISIX Ingress 控制器提供 Helm 安装方式,但是使用原生 YAML 安装,更加有助于理解其原理。
APISIX Ingress 控制器的安装及原理
2023-06-09阅读:309
APISIX 是动态、实时、高性能的 API 网关。它提供丰富的流量管理功能,比如负载均衡、动态上游、金丝雀发布、熔断、认证、可观测性等。既可以使用 APISIX API 网关处理传统的南北向流量,也可以使用它处理服务间的东西向流量。同时,它也可被用作 Kubernetes Ingress 控制器。
APISIX Ingress 控制器提供 Helm 安装方式,但是使用原生 YAML 安装,更加有助于理解其原理。
kubectl create ns apisix
# etcd-headless.yamlapiVersion: v1kind: Servicemetadata: name: etcd-headless namespace: apisix labels: app.kubernetes.io/name: etcd annotations: service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"spec: type: ClusterIP clusterIP: None ports: - name: "client" port: 2379 targetPort: client - name: "peer" port: 2380 targetPort: peer selector: app.kubernetes.io/name: etcd---# etcd.yamlapiVersion: apps/v1kind: StatefulSetmetadata: name: etcd namespace: apisix labels: app.kubernetes.io/name: etcdspec: selector: matchLabels: app.kubernetes.io/name: etcd serviceName: etcd-headless podManagementPolicy: Parallel replicas: 1 updateStrategy: type: RollingUpdate template: metadata: labels: app.kubernetes.io/name: etcd spec: securityContext: fsGroup: 1001 runAsUser: 1001 containers: - name: etcd image: docker.io/bitnami/etcd:3.4.14-debian-10-r0 imagePullPolicy: "IfNotPresent" # command: # - /scripts/setup.sh env: - name: BITNAMI_DEBUG value: "false" - name: MY_POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: ETCDCTL_API value: "3" - name: ETCD_NAME value: "$(MY_POD_NAME)" - name: ETCD_DATA_DIR value: /etcd/data - name: ETCD_ADVERTISE_CLIENT_URLS value: "http://$(MY_POD_NAME).etcd-headless.apisix.svc.cluster.local:2379" - name: ETCD_LISTEN_CLIENT_URLS value: "http://0.0.0.0:2379" - name: ETCD_INITIAL_ADVERTISE_PEER_URLS value: "http://$(MY_POD_NAME).etcd-headless.apisix.svc.cluster.local:2380" - name: ETCD_LISTEN_PEER_URLS value: "http://0.0.0.0:2380" - name: ALLOW_NONE_AUTHENTICATION value: "yes" ports: - name: client containerPort: 2379 - name: peer containerPort: 2380 volumeMounts: - name: data mountPath: /etcd # If you don't have a storage provisioner or don't want to use persistence volume, you could use an `emptyDir` as follow. # volumes: # - name: data # emptyDir: {} volumeClaimTemplates: - metadata: name: data spec: accessModes: - "ReadWriteOnce" resources: requests: storage: "8Gi"
apiVersion: v1kind: ConfigMapmetadata: name: apisix-conf namespace: apisixdata: config.yaml: |- apisix: node_listen: 9080 # APISIX listening port enable_heartbeat: true enable_admin: true enable_admin_cors: true enable_debug: false enable_dev_mode: false # Sets nginx worker_processes to 1 if set to true enable_reuseport: true # Enable nginx SO_REUSEPORT switch if set to true. enable_ipv6: true config_center: etcd # etcd: use etcd to store the config value allow_admin: # Module ngx_http_access_module - 0.0.0.0/0 port_admin: 9180 # Default token when use API to call for Admin API. # *NOTE*: Highly recommended to modify this value to protect APISIX's Admin API. # Disabling this configuration item means that the Admin API does not # require any authentication. admin_key: # admin: can everything for configuration data - name: "admin" key: edd1c9f034335f136f87ad84b625c8f1 role: admin # viewer: only can view configuration data - name: "viewer" key: 4054f7cf07e344346cd3f287985e76a2 role: viewer # dns_resolver: # - 127.0.0.1 dns_resolver_valid: 30 resolver_timeout: 5 nginx_config: # config for render the template to generate nginx.conf error_log: "/dev/stderr" error_log_level: "warn" # warn,error worker_rlimit_nofile: 20480 # the number of files a worker process can open, should be larger than worker_connections event: worker_connections: 10620 http: access_log: "/dev/stdout" keepalive_timeout: 60s # timeout during which a keep-alive client connection will stay open on the server side. client_header_timeout: 60s # timeout for reading client request header, then 408 (Request Time-out) error is returned to the client client_body_timeout: 60s # timeout for reading client request body, then 408 (Request Time-out) error is returned to the client send_timeout: 10s # timeout for transmitting a response to the client.then the connection is closed underscores_in_headers: "on" # default enables the use of underscores in client request header fields real_ip_header: "X-Real-IP" # Module ngx_http_realip_module real_ip_from: # Module ngx_http_realip_module - 127.0.0.1 - 'unix:' etcd: host: - "http://etcd-headless.apisix.svc.cluster.local:2379" prefix: "/apisix" # apisix configurations prefix timeout: 30 # seconds plugins: # plugin list - api-breaker - authz-keycloak - basic-auth - batch-requests - consumer-restriction - cors - echo - fault-injection - grpc-transcode - hmac-auth - http-logger - ip-restriction - jwt-auth - kafka-logger - key-auth - limit-conn - limit-count - limit-req - node-status - openid-connect - prometheus - proxy-cache - proxy-mirror - proxy-rewrite - redirect - referer-restriction - request-id - request-validation - response-rewrite - serverless-post-function - serverless-pre-function - sls-logger - syslog - tcp-logger - udp-logger - uri-blocker - wolf-rbac - zipkin - traffic-split stream_plugins: - mqtt-proxy
apiVersion: v1kind: ConfigMapmetadata: name: apisix-conf namespace: apisixdata: config.yaml: |- apisix: node_listen: 9080 # APISIX listening port enable_heartbeat: true enable_admin: true enable_admin_cors: true enable_debug: false enable_dev_mode: false # Sets nginx worker_processes to 1 if set to true enable_reuseport: true # Enable nginx SO_REUSEPORT switch if set to true. enable_ipv6: true config_center: etcd # etcd: use etcd to store the config value allow_admin: # Module ngx_http_access_module - 0.0.0.0/0 port_admin: 9180 # Default token when use API to call for Admin API. # *NOTE*: Highly recommended to modify this value to protect APISIX's Admin API. # Disabling this configuration item means that the Admin API does not # require any authentication. admin_key: # admin: can everything for configuration data - name: "admin" key: edd1c9f034335f136f87ad84b625c8f1 role: admin # viewer: only can view configuration data - name: "viewer" key: 4054f7cf07e344346cd3f287985e76a2 role: viewer # dns_resolver: # - 127.0.0.1 dns_resolver_valid: 30 resolver_timeout: 5 nginx_config: # config for render the template to generate nginx.conf error_log: "/dev/stderr" error_log_level: "warn" # warn,error worker_rlimit_nofile: 20480 # the number of files a worker process can open, should be larger than worker_connections event: worker_connections: 10620 http: access_log: "/dev/stdout" keepalive_timeout: 60s # timeout during which a keep-alive client connection will stay open on the server side. client_header_timeout: 60s # timeout for reading client request header, then 408 (Request Time-out) error is returned to the client client_body_timeout: 60s # timeout for reading client request body, then 408 (Request Time-out) error is returned to the client send_timeout: 10s # timeout for transmitting a response to the client.then the connection is closed underscores_in_headers: "on" # default enables the use of underscores in client request header fields real_ip_header: "X-Real-IP" # Module ngx_http_realip_module real_ip_from: # Module ngx_http_realip_module - 127.0.0.1 - 'unix:' etcd: host: - "http://etcd-headless.apisix.svc.cluster.local:2379" prefix: "/apisix" # apisix configurations prefix timeout: 30 # seconds plugins: # plugin list - api-breaker - authz-keycloak - basic-auth - batch-requests - consumer-restriction - cors - echo - fault-injection - grpc-transcode - hmac-auth - http-logger - ip-restriction - jwt-auth - kafka-logger - key-auth - limit-conn - limit-count - limit-req - node-status - openid-connect - prometheus - proxy-cache - proxy-mirror - proxy-rewrite - redirect - referer-restriction - request-id - request-validation - response-rewrite - serverless-post-function - serverless-pre-function - sls-logger - syslog - tcp-logger - udp-logger - uri-blocker - wolf-rbac - zipkin - traffic-split stream_plugins: - mqtt-proxy
apiVersion: apps/v1kind: Deploymentmetadata: name: apisix namespace: apisix labels: app.kubernetes.io/name: apisixspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: apisix template: metadata: labels: app.kubernetes.io/name: apisix spec: containers: - name: apisix image: "apache/apisix:2.5-alpine" imagePullPolicy: IfNotPresent ports: - name: http containerPort: 9080 protocol: TCP - name: tls containerPort: 9443 protocol: TCP - name: admin containerPort: 9180 protocol: TCP readinessProbe: failureThreshold: 6 initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 9080 timeoutSeconds: 1 lifecycle: preStop: exec: command: - /bin/sh - -c - "sleep 30" volumeMounts: - mountPath: /usr/local/apisix/conf/config.yaml name: apisix-config subPath: config.yaml resources: {} volumes: - configMap: name: apisix-conf name: apisix-config
kubectl -n apisix exec -it apisix-7644966c4d-cl4k6 -- curl http://127.0.0.1:9080
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl http://127.0.0.1:9080
kubectl create ns demokubectl label namespace demo apisix.ingress=watching # 给 demo 命名空间添加 apisix.ingress 标签kubectl -n demo run httpbin --image-pull-policy=IfNotPresent --image kennethreitz/httpbin --port 80kubectl -n demo expose pod httpbin --port 80
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl http://httpbin.demo/get
{ "args": {}, "headers": { "Accept": "*/*", "Host": "httpbin.demo", "User-Agent": "curl/7.67.0" }, "origin": "172.17.0.1", "url": "http://httpbin.demo/get" }
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl "http://127.0.0.1:9180/apisix/admin/routes/1" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '{ "uri": "/*", "host": "httpbin.org", "upstream": { "type": "roundrobin", "nodes": { "httpbin.demo:80": 1 } }}'
{"action":"set","node":{"key":"\/apisix\/routes\/1","value":{"status":1,"create_time":1621408897,"upstream":{"pass_host":"pass","type":"roundrobin","hash_on":"vars","nodes":{"httpbin.demo:80":1},"scheme":"http"},"update_time":1621408897,"priority":0,"host":"httpbin.org","id":"1","uri":"\/*"}}}
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl "http://127.0.0.1:9180/apisix/admin/routes/1" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
{"action":"get","node":{"key":"\/apisix\/routes\/1","value":{"upstream":{"pass_host":"pass","type":"roundrobin","scheme":"http","hash_on":"vars","nodes":{"httpbin.demo:80":1}},"id":"1","create_time":1621408897,"update_time":1621408897,"host":"httpbin.org","priority":0,"status":1,"uri":"\/*"}},"count":"1"}
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl "http://127.0.0.1:9080/get" -H 'Host: httpbin.org'
{ "args": {}, "headers": { "Accept": "*/*", "Host": "httpbin.org", "User-Agent": "curl/7.67.0", "X-Forwarded-Host": "httpbin.org" }, "origin": "127.0.0.1", "url": "http://httpbin.org/get" }
下面是来自 apisix-helm-chart 的示例配置:apiVersion: v1kind: ServiceAccountmetadata: name: apisix-ingress-controller namespace: apisix---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: apisix-clusterrole namespace: apisixrules: - apiGroups: - "" resources: - configmaps - endpoints - persistentvolumeclaims - pods - replicationcontrollers - replicationcontrollers/scale - serviceaccounts - services - secrets verbs: - get - list - watch - apiGroups: - "" resources: - bindings - events - limitranges - namespaces/status - pods/log - pods/status - replicationcontrollers/status - resourcequotas - resourcequotas/status verbs: - get - list - watch - apiGroups: - "" resources: - namespaces verbs: - get - list - watch - apiGroups: - apps resources: - controllerrevisions - daemonsets - deployments - deployments/scale - replicasets - replicasets/scale - statefulsets - statefulsets/scale verbs: - get - list - watch - apiGroups: - autoscaling resources: - horizontalpodautoscalers verbs: - get - list - watch - apiGroups: - batch resources: - cronjobs - jobs verbs: - get - list - watch - apiGroups: - extensions resources: - daemonsets - deployments - deployments/scale - ingresses - networkpolicies - replicasets - replicasets/scale - replicationcontrollers/scale verbs: - get - list - watch - apiGroups: - policy resources: - poddisruptionbudgets verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses - networkpolicies verbs: - get - list - watch - apiGroups: - metrics.k8s.io resources: - pods verbs: - get - list - watch - apiGroups: - apisix.apache.org resources: - apisixroutes - apisixroutes/status - apisixupstreams - apisixupstreams/status - apisixtlses - apisixtlses/status - apisixclusterconfigs - apisixclusterconfigs/status - apisixconsumers - apisixconsumers/status - apisixpluginconfigs verbs: - get - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - '*'---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: apisix-clusterrolebinding namespace: apisixroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: apisix-clusterrolesubjects: - kind: ServiceAccount name: apisix-ingress-controller namespace: apisix
git clone https://github.com/apache/apisix-ingress-controller.git --depth 1 cd apisix-ingress-controller/ kubectl apply -k samples/deploy/crd
apiVersion: v1data: config.yaml: | # log options log_level: "debug" log_output: "stderr" http_listen: ":8080" enable_profiling: true kubernetes: kubeconfig: "" resync_interval: "30s" namespace_selector: - "apisix.ingress=watching" ingress_class: "apisix" ingress_version: "networking/v1" apisix_route_version: "apisix.apache.org/v2" apisix: default_cluster_base_url: "http://apisix-admin.apisix:9180/apisix/admin" default_cluster_admin_key: "edd1c9f034335f136f87ad84b625c8f1"kind: ConfigMapmetadata: name: apisix-configmap namespace: apisix labels: app.kubernetes.io/name: ingress-controller
apiVersion: v1kind: Servicemetadata: name: apisix-admin namespace: apisix labels: app.kubernetes.io/name: apisixspec: type: ClusterIP ports: - name: apisix-admin port: 9180 targetPort: 9180 protocol: TCP selector: app.kubernetes.io/name: apisix
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X DELETE -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
apiVersion: apps/v1kind: Deploymentmetadata: name: apisix-ingress-controller namespace: apisix labels: app.kubernetes.io/name: ingress-controllerspec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-controller template: metadata: labels: app.kubernetes.io/name: ingress-controller spec: serviceAccountName: apisix-ingress-controller volumes: - name: configuration configMap: name: apisix-configmap items: - key: config.yaml path: config.yaml initContainers: - name: wait-apisix-admin image: busybox:1.28 command: ['sh', '-c', "until nc -z apisix-admin.apisix.svc.cluster.local 9180 ; do echo waiting for apisix-admin; sleep 2; done;"] containers: - name: ingress-controller command: - /ingress-apisix/apisix-ingress-controller - ingress - --config-path - /ingress-apisix/conf/config.yaml image: "apache/apisix-ingress-controller:1.6.0" imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 protocol: TCP livenessProbe: httpGet: path: /healthz port: 8080 readinessProbe: httpGet: path: /healthz port: 8080 resources: {} volumeMounts: - mountPath: /ingress-apisix/conf name: configuration
apiVersion: apisix.apache.org/v2kind: ApisixRoutemetadata: name: httpserver-route namespace: demospec: http: - name: httpbin match: hosts: - local.httpbin.org paths: - /* backends: - serviceName: httpbin servicePort: 80
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl "http://127.0.0.1:9080/get" -H 'Host: local.httpbin.org'
{"error_msg":"404 Route Not Found"}
kubectl -n apisix exec -it $(kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name) -- curl "http://127.0.0.1:9080/get" -H "Host: local.httpbin.org"
{ "args": {}, "headers": { "Accept": "*/*", "Host": "local.httpbin.org", "User-Agent": "curl/7.67.0", "X-Forwarded-Host": "local.httpbin.org" }, "origin": "127.0.0.1", "url": "http://local2.httpbin.org/get"}
地址:北京市海淀区海淀大街38号银科大厦6层
Copyright © 2022 北京星阑科技有限公司. 京ICP备19053406号
提交成功