Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs - add jobs use case for service mesh k8s #18037

Merged
merged 10 commits into from
Jul 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 196 additions & 22 deletions website/content/docs/k8s/connect/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,33 @@ Consul service mesh is enabled by default when you install Consul on Kubernetes

If `connectInject.default` is set to `false` or you want to explicitly enable service mesh sidecar proxy injection for a specific deployment, add the `consul.hashicorp.com/connect-inject` annotation to the pod specification template and set it to `true` when connecting services to the mesh.

### Example
### Service names

When the service is onboarded, the name registered in Consul is set to the name of the Kubernetes Service associated with the Pod. You can specify a custom name for the service in the [`consul.hashicorp.com/connect-service` annotation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service), but if ACLs are enabled, then the name of the service registered in Consul must match the Pod's `ServiceAccount` name.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When the service is onboarded, the name registered in Consul is set to the name of the Kubernetes Service associated with the Pod. You can specify a custom name for the service in the [`consul.hashicorp.com/connect-service` annotation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service), but if ACLs are enabled, then the name of the service registered in Consul must match the Pod's `ServiceAccount` name.
When the service is onboarded, the name registered in Consul is set to the name of the Kubernetes Service associated with the Pod. You can use the [`consul.hashicorp.com/connect-service` annotation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service) to specify a custom name for the service, but if ACLs are enabled then the name of the service registered in Consul must match the Pod's `ServiceAccount` name.

Re-ordering these phrases to keep the action ("specify a custom name") close to the clarification ("but").


### Transparent proxy mode

By default, the Consul service mesh runs in transparent proxy mode. This mode forces inbound and outbound traffic through the sidecar proxy even though the service binds to all interfaces. Transparent proxy infers the location of upstream services using Consul service intentions, and also allows you to use Kubernetes DNS as you normally would for your workloads.

When transparent proxy mode is enabled, all service-to-service traffic is required to use mTLS. While onboarding new services to service mesh, your network may have mixed mTLS and non-mTLS traffic, which can result in broken service-to-service communication. You can temporarily enable permissive mTLS mode during the onboarding process so that existing mesh services can accept traffic from services that are not yet fully onboarded. Permissive mTLS enables sidecar proxies to access both mTLS and non-mTLS traffic. Refer to [Onboard mesh services in transparent proxy mode](/consul/docs/k8s/connect/onboarding-tproxy-mode) for additional information.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When transparent proxy mode is enabled, all service-to-service traffic is required to use mTLS. While onboarding new services to service mesh, your network may have mixed mTLS and non-mTLS traffic, which can result in broken service-to-service communication. You can temporarily enable permissive mTLS mode during the onboarding process so that existing mesh services can accept traffic from services that are not yet fully onboarded. Permissive mTLS enables sidecar proxies to access both mTLS and non-mTLS traffic. Refer to [Onboard mesh services in transparent proxy mode](/consul/docs/k8s/connect/onboarding-tproxy-mode) for additional information.
When transparent proxy mode is enabled, all service-to-service traffic is required to use mTLS. When onboarding new services to service mesh, your network may have mixed mTLS and non-mTLS traffic, which can result in broken service-to-service communication. You can temporarily enable permissive mTLS mode during the onboarding process so that existing mesh services can accept traffic from services that are not yet fully onboarded. Permissive mTLS enables sidecar proxies to access both mTLS and non-mTLS traffic. Refer to [Onboard mesh services in transparent proxy mode](/consul/docs/k8s/connect/onboarding-tproxy-mode) for additional information.


### Kubernetes service mesh workload scenarios

-> **Note:** A Kubernetes Service is **required** to register services on the Consul Service Mesh as Consul monitors the lifecyle of a Kubernetes service and its service instances using the service object. In addition the Kubernetes service is used to register and de-register the service from the Catalog.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-> **Note:** A Kubernetes Service is **required** to register services on the Consul Service Mesh as Consul monitors the lifecyle of a Kubernetes service and its service instances using the service object. In addition the Kubernetes service is used to register and de-register the service from the Catalog.
-> **Note:** A Kubernetes Service is required in order to register services on the Consul service mesh. Consul monitors the lifecyle of the Kubernetes Service and its service instances using the service object. In addition, the Kubernetes service is used to register and de-register the service from Consul's catalog.
  1. Bolding words for semantic emphasis is explicitly discouraged in the style guide.
  2. Lots of inconsistent capitalization. Feel free to modify based on your intent, but here's my thinking:
  • "Kubernetes Service" is fine to capitalize. Like "Kubernetes Pods" we're referring to an external application's concept.
  • We generally prefer "Consul service mesh" instead of "Consul Service Mesh"
  • Similarly, "Consul catalog" is better than "Catalog" for its specificity.


Below are multiple scenarios for registering workloads on Kubernetes onto Consul Service Mesh. Each scenario provides an example Kubernetes manifest to help quickly understand how to use Consul Service Mesh on a specific Kubernetes workload type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Below are multiple scenarios for registering workloads on Kubernetes onto Consul Service Mesh. Each scenario provides an example Kubernetes manifest to help quickly understand how to use Consul Service Mesh on a specific Kubernetes workload type.
The following configurations are examples for registering workloads on Kubernetes into Consul's service mesh in different scenarios. Each scenario provides an example Kubernetes manifest to demonstrate how to use Consul's service mesh with a specific Kubernetes workload type.
  1. We generally prefer "the following examples" instead of "the examples below."
  2. I adjusted the prepositions because they don't sound right. Objects are typically "in" a mesh, not "on" it. I would even suggest "registering workloads on Kubernetes with Consul's service mesh" before "onto Consul's service mesh."
  3. To make the sense more active, the example "demonstrates" instead of "helps [the user] quickly understand"


- [Kubernetes Pods running as a deployment](#kubernetes-pods-running-as-a-deployment)
- [Connecting to mesh-enabled Services](#connecting-to-mesh-enabled-services)
- [Kubernetes Jobs](#kubernetes-jobs)
- [Kubernetes Pods with Multiple ports](#kubernetes-pods-with-multiple-ports)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- [Kubernetes Pods with Multiple ports](#kubernetes-pods-with-multiple-ports)
- [Kubernetes Pods with multiple ports](#kubernetes-pods-with-multiple-ports)


#### Kubernetes Pods running as a deployment

The following example shows a Kubernetes configuration that specifically enables service mesh connections for the `static-server` service. Consul starts and registers a sidecar proxy that listens on port 20000 by default and proxies valid inbound connections to port 8080.

<CodeBlockConfig filename="static-server.yaml">

```yaml
apiVersion: v1
kind: Service
Expand Down Expand Up @@ -72,27 +95,18 @@ spec:
serviceAccountName: static-server
```

To establish a connection to the Pod using service mesh, a client must use another mesh proxy. The client mesh proxy will use Consul service discovery to find all available upstream proxies and their public ports.

### Service names

When the service is onboarded, the name registered in Consul is set to the name of the Kubernetes Service associated with the Pod. You can specify a custom name for the service in the [`consul.hashicorp.com/connect-service` annotation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service), but if ACLs are enabled, then the name of the service registered in Consul must match the Pod's `ServiceAccount` name.

### Transparent proxy mode

By default, the Consul service mesh runs in transparent proxy mode. This mode forces inbound and outbound traffic through the sidecar proxy even though the service binds to all interfaces. Transparent proxy infers the location of upstream services using Consul service intentions, and also allows you to use Kubernetes DNS as you normally would for your workloads.
</CodeBlockConfig>

When transparent proxy mode is enabled, all service-to-service traffic is required to use mTLS. While onboarding new services to service mesh, your network may have mixed mTLS and non-mTLS traffic, which can result in broken service-to-service communication. You can temporarily enable permissive mTLS mode during the onboarding process so that existing mesh services can accept traffic from services that are not yet fully onboarded. Permissive mTLS enables sidecar proxies to access both mTLS and non-mTLS traffic. Refer to [Onboard mesh services in transparent proxy mode](/consul/docs/k8s/connect/onboarding-tproxy-mode) for additional information.
To establish a connection to the Pod using service mesh, a client must use another mesh proxy. The client mesh proxy will use Consul service discovery to find all available upstream proxies and their public ports.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To establish a connection to the Pod using service mesh, a client must use another mesh proxy. The client mesh proxy will use Consul service discovery to find all available upstream proxies and their public ports.
To establish a connection between the Pod and the service mesh, a client must use another mesh proxy. The client mesh proxy uses Consul service discovery to find all available upstream proxies and their public ports.
  1. "Using service mesh" sounded strange to me. Is the service mesh the tool that makes the connection possible? My suggestion is simpler/less direct, but you can reject it if it's inaccurate.
  2. Avoid future tense and use present tense when possible, per style guide.


### Connecting to Mesh-Enabled Services
#### Connecting to Mesh-Enabled Services
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### Connecting to Mesh-Enabled Services
#### Connecting to mesh-enabled Services


The example Deployment specification below configures a Deployment 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 service mesh.

-> **Note:** As of consul-k8s `v0.26.0` and Consul Helm `v0.32.0`, having a Kubernetes
Service is **required** to run services on the Consul Service Mesh.
<CodeBlockConfig filename="static-client.yaml">

```yaml
apiVersion: v1
Expand Down Expand Up @@ -138,6 +152,8 @@ spec:
serviceAccountName: static-client
```

</CodeBlockConfig>

By default when ACLs are enabled or when ACLs default policy is `allow`,
Consul will automatically configure proxies with all upstreams from the same datacenter.
When ACLs are enabled with default `deny` policy,
Expand Down Expand Up @@ -172,7 +188,95 @@ $ kubectl exec deploy/static-client -- curl --silent http://static-server/
command terminated with exit code 52
```

### Kubernetes Pods with Multiple ports
#### Kubernetes Jobs

Kubernetes Jobs run pods that successfully terminate and only make outbound requests to services on the mesh. In order to register a Kubernetes job on the mesh, you must provide an integer value for the `consul.hashicorp.com/sidecar-proxy-lifecycle-shutdown-grace-period-seconds` annotation, and issue a request the `http://127.0.0.1:20600/graceful_shutdown` API endpoint for `consul-dataplane` to gracefully shut down the `consul-dataplane` sidecar after the job is complete. ,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Kubernetes Jobs run pods that successfully terminate and only make outbound requests to services on the mesh. In order to register a Kubernetes job on the mesh, you must provide an integer value for the `consul.hashicorp.com/sidecar-proxy-lifecycle-shutdown-grace-period-seconds` annotation, and issue a request the `http://127.0.0.1:20600/graceful_shutdown` API endpoint for `consul-dataplane` to gracefully shut down the `consul-dataplane` sidecar after the job is complete. ,
Kubernetes Jobs run pods that only make outbound requests to services on the mesh and successfully terminate when they are complete. In order to register a Kubernetes Job with the mesh, you must provide an integer value for the `consul.hashicorp.com/sidecar-proxy-lifecycle-shutdown-grace-period-seconds` annotation. Then, issue a request to the `http://127.0.0.1:20600/graceful_shutdown` API endpoint so that Kubernetes gracefully shuts down the `consul-dataplane` sidecar after the job is complete.

There were a few phrases where it was difficult for me to parse the intent (example: "for consul-dataplane to gracefully shut down the consul-dataplane sidecar - I'm not sure if the repeated dataplane is a typo or not). Similarly, it seemed odd to describe the bJob behavioral sequence as "terminate" and then "make outbound requests" instead of the other way around.

Please double-check these sentences and let me know if you need additional assistance with the phrasing.


Below is an example Kubernetes manifest that deploys a job correctly.

<CodeBlockConfig filename="test-job.yaml">

```yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-job
namespace: default
---
apiVersion: v1
kind: Service
metadata:
name: test-job
namespace: default
spec:
selector:
app: test-job
ports:
- port: 80
---
apiVersion: batch/v1
kind: Job
metadata:
name: test-job
namespace: default
labels:
app: test-job
spec:
template:
metadata:
annotations:
'consul.hashicorp.com/connect-inject': 'true'
'consul.hashicorp.com/sidecar-proxy-lifecycle-shutdown-grace-period-seconds': '5'
labels:
app: test-job
spec:
containers:
- name: test-job
image: alpine/curl:3.14
ports:
- containerPort: 80
command:
- /bin/sh
- -c
- |
echo "Started test job"
sleep 10
echo "Killing proxy"
curl --max-time 2 -s -f -XPOST http://127.0.0.1:20600/graceful_shutdown
sleep 10
echo "Ended test job"
serviceAccountName: test-job
restartPolicy: Never
```

</CodeBlockConfig>

Upon completing the job you should be able to verify that all containers are shut down within the pod.

```shell-session
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-job-49st7 0/2 Completed 0 3m55s
```

```shell-session
$ kubectl get job
NAME COMPLETIONS DURATION AGE
test-job 1/1 30s 4m31s
```

In addition, based on the logs emitted by the pod you can verify that the proxy was indeed shut down prior to job completing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In addition, based on the logs emitted by the pod you can verify that the proxy was indeed shut down prior to job completing.
In addition, based on the logs emitted by the pod you can verify that the proxy was shut down before the Job completed.


```shell-session
$ kubectl logs test-job-49st7 -c test-job
Started test job
Killing proxy
Ended test job
```

#### Kubernetes Pods with Multiple ports
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### Kubernetes Pods with Multiple ports
#### Kubernetes Pods with multiple ports


To configure a pod with multiple ports to be a part of the service mesh and receive and send service mesh traffic, you
will need to add configuration so that a Consul service can be registered per port. This is because services in Consul
currently support a single port per service instance.
Expand All @@ -184,6 +288,9 @@ First, decide on the names for the two Consul services that will correspond to t
chooses the names `web` for `8080` and `web-admin` for `9090`.

Create two service accounts for `web` and `web-admin`:

<CodeBlockConfig filename="multiport-web-sa.yaml">

```yaml
apiVersion: v1
kind: ServiceAccount
Expand All @@ -195,7 +302,14 @@ kind: ServiceAccount
metadata:
name: web-admin
```

</CodeBlockConfig>


Create two Service objects for `web` and `web-admin`:

<CodeBlockConfig filename="multiport-web-svc.yaml">

```yaml
apiVersion: v1
kind: Service
Expand All @@ -221,12 +335,17 @@ spec:
port: 80
targetPort: 9090
```

</CodeBlockConfig>

`web` will target `containerPort` `8080` and select pods labeled `app: web`. `web-admin` will target `containerPort`
`9090` and will also select the same pods.

~> Kubernetes 1.24+ only
In Kubernetes 1.24+ you need to [create a Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets) for each multi-port service that references the ServiceAccount, and the Kubernetes secret must have the same name as the ServiceAccount:

<CodeBlockConfig filename="multiport-web-secret.yaml">

```yaml
apiVersion: v1
kind: Secret
Expand All @@ -245,12 +364,15 @@ metadata:
type: kubernetes.io/service-account-token
```

</CodeBlockConfig>

Create a Deployment with any chosen name, and use the following annotations:
```yaml
consul.hashicorp.com/connect-inject: true
consul.hashicorp.com/transparent-proxy: false
consul.hashicorp.com/connect-service: web,web-admin
consul.hashicorp.com/connect-service-port: 8080,9090
annotations:
'consul.hashicorp.com/connect-inject': 'true'
'consul.hashicorp.com/transparent-proxy': 'false'
'consul.hashicorp.com/connect-service': 'web,web-admin'
'consul.hashicorp.com/connect-service-port': '8080,9090'
```
Note that the order the ports are listed in the same order as the service names, i.e. the first service name `web`
corresponds to the first port, `8080`, and the second service name `web-admin` corresponds to the second port, `9090`.
Expand All @@ -260,7 +382,11 @@ The service account on the pod spec for the deployment should be set to the firs
serviceAccountName: web
```

For reference, the full deployment example could look something like the following:
For reference, a full deployment example is provided below with the correct annotations provided. In addition, the previous yaml manifests can also be combined into
a single manifest for easier deployment.
Comment on lines +385 to +386
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For reference, a full deployment example is provided below with the correct annotations provided. In addition, the previous yaml manifests can also be combined into
a single manifest for easier deployment.
The following deployment example demonstrates the required annotations for the manifest. In addition, the previous YAML manifests can also be combined into
a single manifest for easier deployment.


<CodeBlockConfig filename="multiport-web.yaml">

```yaml
apiVersion: apps/v1
kind: Deployment
Expand Down Expand Up @@ -302,13 +428,61 @@ spec:
serviceAccountName: web
```

</CodeBlockConfig>

After deploying the `web` application, you can test service mesh connections by deploying the `static-client`
application with the configuration in the [previous section](#connecting-to-mesh-enabled-services) and add the
following annotation to the pod template on `static-client`:
`consul.hashicorp.com/connect-service-upstreams: 'web:1234,web-admin:2234'` annotation to the pod template on `static-client`:

<CodeBlockConfig filename="multiport-static-client.yaml" lineNumbers highlight="33">

```yaml
consul.hashicorp.com/connect-service-upstreams: "web:1234,web-admin:2234"
apiVersion: v1
kind: Service
metadata:
# This name will be the service name in Consul.
name: static-client
spec:
selector:
app: static-client
ports:
- port: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: static-client
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: static-client
spec:
replicas: 1
selector:
matchLabels:
app: static-client
template:
metadata:
name: static-client
labels:
app: static-client
annotations:
'consul.hashicorp.com/connect-inject': 'true'
'consul.hashicorp.com/connect-service-upstreams': 'web:1234,web-admin:2234'
spec:
containers:
- name: static-client
image: curlimages/curl:latest
# Just spin & wait forever, we'll use `kubectl exec` to demo
command: ['/bin/sh', '-c', '--']
args: ['while true; do sleep 30; done;']
# If ACLs are enabled, the serviceAccountName must match the Consul service name.
serviceAccountName: static-client
```

</CodeBlockConfig>

If you exec on to a static-client pod, using a command like:
```shell-session
$ kubectl exec -it static-client-5bd667fbd6-kk6xs -- /bin/sh
Expand Down