diff --git a/website/source/docs/platform/k8s/connect.html.md b/website/source/docs/platform/k8s/connect.html.md new file mode 100644 index 0000000000..ba78aa2f0c --- /dev/null +++ b/website/source/docs/platform/k8s/connect.html.md @@ -0,0 +1,264 @@ +--- +layout: "docs" +page_title: "Connect Sidecar - Kubernetes" +sidebar_current: "docs-platform-k8s-connect" +description: |- + Connect is a feature built into to Consul that enables automatic service-to-service authorization and connection encryption across your Consul services. Connect can be used with Kubernetes to secure pod communication with other services. +--- + +# Connect Sidecar on Kubernetes + +[Connect](/docs/connect/index.html) is a feature built into to Consul that enables +automatic service-to-service authorization and connection encryption across +your Consul services. Connect can be used with Kubernetes to secure pod +communication with other pods and external Kubernetes services. + +The Connect sidecar running Envoy can be automatically injected into pods in +your cluster, making configuration for Kubernetes automatic. +This functionality is provided by the +[consul-k8s project](https://github.com/hashicorp/consul-k8s) and can be +automatically installed and configured using the +[Consul Helm chart](/docs/platform/k8s/helm.html). + +## Usage + +When the +[Connect injector is installed](/docs/platform/k8s/connect.html#installation-and-configuration), +the Connect sidecar is automatically added to all pods. This sidecar can both +accept and establish connections using Connect, enabling the pod to communicate +to clients and dependencies exclusively over authorized and encrypted +connections. + +-> **Note:** The pod specifications in this section are valid and use +publicly available images. If you've installed the Connect injector, feel free +to run the pod specifications in this section to try Connect with Kubernetes. +Please note the documentation below this sectionn on how to properly install +and configure the Connect injector. + +### Accepting Inbound Connections + +An example pod is shown below with Connect enabled to accept inbound +connections. Notice that the pod would still be fully functional without +Connect. Minimal to zero modifications are required to pod specifications to +enable Connect in Kubernetes. + +This pod specification starts a server that responds to any +HTTP request with the static text "hello world". + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: static-server + annotations: + "consul.hashicorp.com/connect-inject": "true" +spec: + containers: + - name: static-server + image: hashicorp/http-echo:latest + args: + - -text="hello world" + - -listen=:8080 + ports: + - containerPort: 8080 + name: http +``` + +The only change for Connect is the addition of the +`consul.hashicorp.com/connect-inject` annotation. This enables injection +for this pod. The injector can also be +[configured](/docs/platform/k8s/connect.html#installation-and-configuration) +to automatically inject unless explicitly disabled, but the default +installation requires opt-in using the annotation shown above. + +This will start a Connect sidecar that listens on a random port registered +with Consul and proxies valid inbound connections to port 8080 in the pod. +To establish a connection to the pod using Connect, a client must use another Connect +proxy. The client Connect proxy will use Consul service discovery to find +all available upstream proxies and their public ports. + +In the example above, the server is listening on `:8080`. This means +the server will still bind to the pod IP and allow external connections. +This is useful to transition to Connect by allowing both Connect and +non-Connect connections. To restrict access to only Connect-authorized clients, +any listeners should bind to localhost only (such as `127.0.0.1`). + +### Connecting to Connect-Enabled Services + +The example pod specification below configures a pod that is capable +of establishing connections to our previous example "static-server" service. The +connection to this static text service happens over an authorized and encrypted +connection via Connect. + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: static-client + annotations: + "consul.hashicorp.com/connect-inject": "true" + "consul.hashicorp.com/connect-service-upstreams": "static-server:1234" +spec: + containers: + - name: static-client + image: tutum/curl:latest + # Just spin & wait forever, we'll use `kubectl exec` to demo + command: [ "/bin/sh", "-c", "--" ] + args: [ "while true; do sleep 30; done;" ] +``` + +Pods must specify upstream dependencies with the +[`consul.hashicorp.com/connect-service-upstreams` annotation](/docs/platform/k8s/connect.html#consul-hashicorp-com-connect-service-upstreams). +This annotation declares the names of any upstream dependencies and a +local port for the proxy to listen on. When a connection is established to that local +port, the proxy establishes a connection to the target service +("static-server" in this example) using +mutual TLS and identifying as the source service ("static-client" in this +example). + +The injector will also set environment variables `_CONNECT_SERVICE_HOST` +and `_CONNECT_SERVICE_PORT` in every container in the pod for every defined +upstream. This is analogous to the standard Kubernetes service environment variables, but +point instead to the correct local proxy port to establish connections via +Connect. + +Any containers running in the pod that need to establish connections +to dependencies must be reconfigured to use the local upstream address either +directly or using the environment variables set by the injector (defined above). +This means pods should not use Kubernetes service DNS or environment +variables for these connections. + + +We can verify access to the static text server using `kubectl exec`. Notice +that we use the local address and port from the upstream annotation (1234) +for this verification. + +```sh +$ kubectl exec static-client -- curl -s http://127.0.0.1:1234/ +"hello world" +``` + +We can control access to the server using [intentions](/docs/connect/intentions.html). +If you use the Consul UI or [CLI](/docs/commands/intention/create.html) to +create a deny [intention](/docs/connect/intentions.html) between +"static-client" and "static-server", connections are immediately rejected +without updating either of the running pods. You can then remove this +intention to allow connections again. + +```sh +$ kubectl exec static-client -- curl -s http://127.0.0.1:1234/ +command terminated with exit code 52 +``` + +### Available Annotations + +Annotations can be used to configure the injection behavior. + +* `consul.hashicorp.com/connect-inject` - If this is "true" then injection + is enabled. If this is "false" then injection is explicitly disabled. + The default injector behavior requires pods to opt-in to injection by + specifying this value as "true". This default can be changed in the + injector's configuration if desired. + +* `consul.hashicorp.com/connect-service` - For pods that accept inbound + connections, this specifies the name of the service that is being + served. This defaults to the name of the first container in the pod. + +* `consul.hashicorp.com/connect-service-port` - For pods that accept inbound + connections, this specifies the port to route inbound connections to. This + is the port that the service is listening on. The service port defaults to + the first exposed port on any container in the pod. If specified, the value + can be the _name_ of a configured port, such as "http" or it can be a direct + port value such as "8080". This is the port of the _service_, the proxy + public listener will listen on a dynamic port. + +* `consul.hashicorp.com/connect-service-upstreams` - The list of upstream + services that this pod needs to connect to via Connect along with a static + local port to listen for those connections. Example: `db:1234,auth:6789` + will start two local listeners for `db` on port 1234 and `auth` on port + 6789, respectively. The name of the service is the name of the service + registered with Consul. This value defaults to no upstreams. + +### Deployments, StatefulSets, etc. + +The annotations for configuring Connect must be on the pod specification. +Since higher level resources such as Deployments wrap pod specification +templates, Connect can be used with all of these higher level constructs, too. + +An example `Deployment` below shows how to enable Connect injection: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: consul-example-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: consul-example + template: + metadata: + labels: + app: consul-example + annotations: + "consul.hashicorp.com/connect-inject": "true" + spec: + containers: + - name: example + image: "nginx" +``` + +~> **A common mistake** is to set the annotation on the Deployment or +other resource. Ensure that the injector annotations are specified on +the _pod specification template_ as shown above. + +## Installation and Configuration + +The Connect sidecar proxy is injected via a +[mutating admission webhook](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) +provided by the +[consul-k8s project](https://github.com/hashicorp/consul-k8s). +This enables the automatic pod mutation shown in the usage section above. +Installation of the mutating admission webhook is automated using the +[Helm chart](/docs/platform/k8s/helm.html). + +To install the Connect injector, enable the Connect injection feature using +[Helm values](/docs/platform/k8s/helm.html#configuration-values-) and +upgrade the installation using `helm upgrade` for existing installs or +`helm install` for a fresh install. The Connect injector **also requires** +[client agents](/docs/platform/k8s/helm.html#v-client) are enabled on +the node with pods that are using Connect and that +[gRPC is enabled](/docs/platform/k8s/helm.html#v-client-grpc). + +```yaml +connectInject: + enabled: true + +client: + enabled: true + grpc: true +``` + +This will configure the injector to inject when the +[injection annotation](#) +is present. Other values in the Helm chart can be used to limit the namespaces +the injector runs in, enable injection by default, and more. + +As noted above, the Connect auto-injection requires that local client agents +are configured. These client agents must be successfully joined to a Consul +cluster. +The Consul server cluster can run either in or out of a Kubernetes cluster. + +### Verifying the Installation + +To verify the installation, run the +["Accepting Inbound Connections"](/docs/platform/k8s/connect.html#accepting-inbound-connections) +example from the "Usage" section above. After running this example, run +`kubectl get pod static-server -o yaml`. In the raw YAML output, you should +see injected Connect containers and an annotation +`consul.hashicorp.com/connect-inject-status` set to `injected`. This +confirms that injection is working properly. + +If you do not see this, then use `kubectl logs` against the injector pod +and note any errors. diff --git a/website/source/docs/platform/k8s/helm.html.md b/website/source/docs/platform/k8s/helm.html.md index d4c80b1d5d..832dded49c 100644 --- a/website/source/docs/platform/k8s/helm.html.md +++ b/website/source/docs/platform/k8s/helm.html.md @@ -198,6 +198,11 @@ and consider if they're appropriate for your deployment. The name of the Docker image (including any tag) for the containers running Consul client agents. + - `grpc` (`boolean: false`) - + If true, agents will enable their GRPC listener on port 8502 and expose + it to the host. This will use slightly more resources, but is required for + [Connect](/docs/platform/k8s/connect.html). + - `extraConfig` (`string: "{}"`) - A raw string of extra JSON or HCL configuration for Consul clients. This will be saved as-is into a ConfigMap that is read by the Consul agents. @@ -292,3 +297,60 @@ and consider if they're appropriate for your deployment. by Kubernetes. The available service types are documented on [the Kubernetes website](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types). +* `connectInject` - Values that + configure running the [Connect injector](/docs/platform/k8s/connect.html). + + - `enabled` (`boolean: false`) - + If true, the chart will install all the resources necessary for the + Connect injector process to run. This will enable the injector but will + require pods to opt-in with an annotation by default. + + - `imageConsul` (`string: global.image`) - + The name of the Docker image (including any tag) for Consul. This is used + for proxy service registration, Envoy configuration, etc. + + - `imageEnvoy` (`string: ""`) - + The name of the Docker image (including any tag) for the Envoy sidecar. + `envoy` must be on the executable path within this image. This Envoy + version must be compatible with the Consul version used by the injector. + This defaults to letting the injector choose the Envoy image, which is + usually `envoy/envoy-alpine`. + + - `default` (`boolean: false`) - + If true, the injector will inject the Connect sidecar into all pods by + default. Otherwise, pods must specify the + [injection annotation](/docs/platform/k8s/connect.html#consul-hashicorp-com-connect-inject) + to opt-in to Connect injection. If this is true, pods can use the same + annotation to explicitly opt-out of injection. + + - `namespaceSelector` (`string: ""`) - + A [selector](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) + for restricting injection to only matching namespaces. By default + all namespaces except the system namespace will have injection enabled. + + - `certs` - + The certs section configures how the webhook TLS certs are configured. + These are the TLS certs for the Kube apiserver communicating to the + webhook. By default, the injector will generate and manage its own certs, + but this requires the ability for the injector to update its own + `MutatingWebhookConfiguration`. In a production environment, custom certs + should probably be used. Configure the values below to enable this. + + * `secretName` (`string: null`) - + secretName is the name of the Kubernetes secret that has the TLS certificate and + private key to serve the injector webhook. If this is null, then the + injector will default to its automatic management mode. + + * `caBundle` (`string: ""`) - + The PEM-encoded CA public certificate bundle for the TLS certificate served by the + injector. This must be specified as a string and can't come from a + secret because it must be statically configured on the Kubernetes + `MutatingAdmissionWebhook` resource. This only needs to be specified + if `secretName` is not null. + + * `certName` (`string: "tls.crt"`) - + The name of the certificate file within the `secretName` secret. + + * `keyName` (`string: "tls.key"`) - + The name of the private key for the certificate file within the + `secretName` secret. diff --git a/website/source/layouts/docs.erb b/website/source/layouts/docs.erb index bfd1ee72ca..51414a6d4a 100644 --- a/website/source/layouts/docs.erb +++ b/website/source/layouts/docs.erb @@ -302,6 +302,9 @@ > Nomad + > + Kubernetes + > Security @@ -326,6 +329,9 @@ > Service Sync + > + Connect Sidecar +