mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
Add NATS on K8S contents (#17)
* Add NATS on K8S contents Signed-off-by: Waldemar Quevedo <wally@synadia.com>
This commit is contained in:
parent
94db70a982
commit
ccb05cdf92
@ -186,3 +186,10 @@
|
|||||||
* [Developing a Client](nats-protocol/nats-protocol/nats-client-dev.md)
|
* [Developing a Client](nats-protocol/nats-protocol/nats-client-dev.md)
|
||||||
* [NATS Cluster Protocol](nats-protocol/nats-server-protocol.md)
|
* [NATS Cluster Protocol](nats-protocol/nats-server-protocol.md)
|
||||||
|
|
||||||
|
## NATS on Kubernetes
|
||||||
|
|
||||||
|
* [Introduction](nats-kubernetes/README.md)
|
||||||
|
* [NATS Streaming Cluster with FT Mode](nats-kubernetes/stan-ft-k8s-aws.md)
|
||||||
|
* [NATS + Prometheus Operator](nats-kubernetes/prometheus-and-nats-operator)
|
||||||
|
* [NATS + Cert Manager](nats-kubernetes/nats-cluster-and-cert-manager.md)
|
||||||
|
* [Securing a NATS Cluster with cfssl](nats-kubernetes/operator-tls-setup-with-cfssl.md)
|
||||||
|
58
nats-kubernetes/README.md
Normal file
58
nats-kubernetes/README.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# NATS on Kubernetes
|
||||||
|
|
||||||
|
In this section you can find several examples of how to deploy NATS, NATS Streaming
|
||||||
|
and other tools from the NATS ecosystem on Kubernetes.
|
||||||
|
|
||||||
|
* [Getting Started](README.md#getting-started)
|
||||||
|
* [Creating a NATS Streaming Cluster in k8s with FT mode](stan-ft-k8s-aws.md)
|
||||||
|
* [NATS + Prometheus Operator](prometheus-and-nats-operator)
|
||||||
|
* [NATS + Cert Manager in k8s](nats-cluster-and-cert-manager.md)
|
||||||
|
* [Securing a NATS Cluster using cfssl](operator-tls-setup-with-cfssl.md)
|
||||||
|
|
||||||
|
|
||||||
|
## Running NATS on K8S
|
||||||
|
|
||||||
|
### Getting started
|
||||||
|
|
||||||
|
The fastest and easiest way to get started is with just one shell command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -sSL https://nats-io.github.io/k8s/setup.sh | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
*In case you don't have a cluster already, you can find some notes on how to create a small cluster using one of the hosted Kubernetes providers [here](https://github.com/nats-io/k8s/docs/create-k8s-cluster.md).*
|
||||||
|
|
||||||
|
This will run a `nats-setup` container with the [required policy](https://github.com/nats-io/k8s/blob/master/setup/bootstrap-policy.yml)
|
||||||
|
and deploy a NATS cluster on Kubernetes with external access, TLS and
|
||||||
|
decentralized authorization.
|
||||||
|
|
||||||
|
[](https://asciinema.org/a/282135)
|
||||||
|
|
||||||
|
By default, the installer will deploy the [Prometheus Operator](https://github.com/coreos/prometheus-operator) and the
|
||||||
|
[Cert Manager](https://github.com/jetstack/cert-manager) for metrics and TLS support, and the NATS instances will
|
||||||
|
also bind the 4222 host port for external access.
|
||||||
|
|
||||||
|
You can customize the installer to install without TLS or without Auth
|
||||||
|
to have a simpler setup as follows:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Disable TLS
|
||||||
|
curl -sSL https://nats-io.github.io/k8s/setup.sh | sh -s -- --without-tls
|
||||||
|
|
||||||
|
# Disable Auth and TLS (also disables NATS surveyor and NATS Streaming)
|
||||||
|
curl -sSL https://nats-io.github.io/k8s/setup.sh | sh -s -- --without-tls --without-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: Since [NATS Streaming](https://github.com/nats-io/nats-streaming-server) will be running as a [leafnode](https://github.com/nats-io/docs/tree/master/leafnodes) to NATS
|
||||||
|
(under the STAN account) and that [NATS Surveyor](https://github.com/nats-io/nats-surveyor)
|
||||||
|
requires the [system account](,,/nats-server/nats_admin/sys_accounts) to monitor events, disabling auth also means that NATS Streaming and NATS Surveyor based monitoring will be disabled.
|
||||||
|
|
||||||
|
The monitoring dashboard setup using NATS Surveyor can be accessed by using port-forward:
|
||||||
|
|
||||||
|
kubectl port-forward deployments/nats-surveyor-grafana 3000:3000
|
||||||
|
|
||||||
|
Next, open the following URL in your browser:
|
||||||
|
|
||||||
|
http://127.0.0.1:3000/d/nats/nats-surveyor?refresh=5s&orgId=1
|
||||||
|
|
||||||
|

|
166
nats-kubernetes/nats-cluster-and-cert-manager.md
Normal file
166
nats-kubernetes/nats-cluster-and-cert-manager.md
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
```text
|
||||||
|
kubectl create namespace cert-manager
|
||||||
|
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
|
||||||
|
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7/deploy/manifests/cert-manager.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: certmanager.k8s.io/v1alpha1
|
||||||
|
kind: ClusterIssuer
|
||||||
|
metadata:
|
||||||
|
name: selfsigning
|
||||||
|
spec:
|
||||||
|
selfSigned: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
clusterissuer.certmanager.k8s.io/selfsigning unchanged
|
||||||
|
```
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
apiVersion: certmanager.k8s.io/v1alpha1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: nats-ca
|
||||||
|
spec:
|
||||||
|
secretName: nats-ca
|
||||||
|
duration: 8736h # 1 year
|
||||||
|
renewBefore: 240h # 10 days
|
||||||
|
issuerRef:
|
||||||
|
name: selfsigning
|
||||||
|
kind: ClusterIssuer
|
||||||
|
commonName: nats-ca
|
||||||
|
organization:
|
||||||
|
- Your organization
|
||||||
|
isCA: true
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
certificate.certmanager.k8s.io/nats-ca configured
|
||||||
|
```
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
apiVersion: certmanager.k8s.io/v1alpha1
|
||||||
|
kind: Issuer
|
||||||
|
metadata:
|
||||||
|
name: nats-ca
|
||||||
|
spec:
|
||||||
|
ca:
|
||||||
|
secretName: nats-ca
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
issuer.certmanager.k8s.io/nats-ca created
|
||||||
|
```
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
apiVersion: certmanager.k8s.io/v1alpha1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: nats-server-tls
|
||||||
|
spec:
|
||||||
|
secretName: nats-server-tls
|
||||||
|
duration: 2160h # 90 days
|
||||||
|
renewBefore: 240h # 10 days
|
||||||
|
issuerRef:
|
||||||
|
name: nats-ca
|
||||||
|
kind: Issuer
|
||||||
|
organization:
|
||||||
|
- Your organization
|
||||||
|
commonName: nats.default.svc.cluster.local
|
||||||
|
dnsNames:
|
||||||
|
- nats.default.svc
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
certificate.certmanager.k8s.io/nats-server-tls created
|
||||||
|
```
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
apiVersion: certmanager.k8s.io/v1alpha1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: nats-routes-tls
|
||||||
|
spec:
|
||||||
|
secretName: nats-routes-tls
|
||||||
|
duration: 2160h # 90 days
|
||||||
|
renewBefore: 240h # 10 days
|
||||||
|
issuerRef:
|
||||||
|
name: nats-ca
|
||||||
|
kind: Issuer
|
||||||
|
organization:
|
||||||
|
- Your organization
|
||||||
|
commonName: "*.nats-mgmt.default.svc.cluster.local"
|
||||||
|
dnsNames:
|
||||||
|
- "*.nats-mgmt.default.svc"
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
certificate.certmanager.k8s.io/nats-routes-tls configured
|
||||||
|
```
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
apiVersion: "nats.io/v1alpha2"
|
||||||
|
kind: "NatsCluster"
|
||||||
|
metadata:
|
||||||
|
name: "nats"
|
||||||
|
spec:
|
||||||
|
# Number of nodes in the cluster
|
||||||
|
size: 3
|
||||||
|
version: "1.4.1"
|
||||||
|
|
||||||
|
tls:
|
||||||
|
# Certificates to secure the NATS client connections:
|
||||||
|
serverSecret: "nats-server-tls"
|
||||||
|
|
||||||
|
# Name of the CA in serverSecret
|
||||||
|
serverSecretCAFileName: "ca.crt"
|
||||||
|
|
||||||
|
# Name of the key in serverSecret
|
||||||
|
serverSecretKeyFileName: "tls.key"
|
||||||
|
|
||||||
|
# Name of the certificate in serverSecret
|
||||||
|
serverSecretCertFileName: "tls.crt"
|
||||||
|
|
||||||
|
# Certificates to secure the routes.
|
||||||
|
routesSecret: "nats-routes-tls"
|
||||||
|
|
||||||
|
# Name of the CA in routesSecret
|
||||||
|
routesSecretCAFileName: "ca.crt"
|
||||||
|
|
||||||
|
# Name of the key in routesSecret
|
||||||
|
routesSecretKeyFileName: "tls.key"
|
||||||
|
|
||||||
|
# Name of the certificate in routesSecret
|
||||||
|
routesSecretCertFileName: "tls.crt"
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
natscluster.nats.io/nats created
|
||||||
|
```
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
kubectl get pods -o wide
|
||||||
|
```
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
|
||||||
|
nats-1 1/1 Running 0 4s 172.17.0.8 minikube <none>
|
||||||
|
nats-2 1/1 Running 0 3s 172.17.0.9 minikube <none>
|
||||||
|
nats-3 1/1 Running 0 2s 172.17.0.10 minikube <none>
|
||||||
|
```
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
kubectl logs nats-1
|
||||||
|
```
|
||||||
|
```text
|
||||||
|
: [1] 2019/05/08 22:35:11.192781 [INF] Starting nats-server version 1.4.1
|
||||||
|
: [1] 2019/05/08 22:35:11.192819 [INF] Git commit [3e64f0b]
|
||||||
|
: [1] 2019/05/08 22:35:11.192952 [INF] Starting http monitor on 0.0.0.0:8222
|
||||||
|
: [1] 2019/05/08 22:35:11.192981 [INF] Listening for client connections on 0.0.0.0:4222
|
||||||
|
: [1] 2019/05/08 22:35:11.192987 [INF] TLS required for client connections
|
||||||
|
: [1] 2019/05/08 22:35:11.192989 [INF] Server is ready
|
||||||
|
: [1] 2019/05/08 22:35:11.193123 [INF] Listening for route connections on 0.0.0.0:6222
|
||||||
|
: [1] 2019/05/08 22:35:12.487758 [INF] 172.17.0.9:49444 - rid:1 - Route connection created
|
||||||
|
: [1] 2019/05/08 22:35:13.450067 [INF] 172.17.0.10:46286 - rid:2 - Route connection created
|
||||||
|
```
|
422
nats-kubernetes/operator-tls-setup-with-cfssl.md
Executable file
422
nats-kubernetes/operator-tls-setup-with-cfssl.md
Executable file
@ -0,0 +1,422 @@
|
|||||||
|
# Secure NATS Cluster in Kubernetes using the NATS Operator
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Clients TLS setup
|
||||||
|
- TLS based auth certs via secret
|
||||||
|
+ Reloading supported by only updating secret
|
||||||
|
- Routes TLS setup
|
||||||
|
- Advertising public IP per NATS server for external access
|
||||||
|
|
||||||
|
### Creating the Certificates
|
||||||
|
|
||||||
|
#### Generating the Root CA Certs
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"CN": "nats.io",
|
||||||
|
"key": {
|
||||||
|
"algo": "rsa",
|
||||||
|
"size": 2048
|
||||||
|
},
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"OU": "nats.io"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
(
|
||||||
|
cd certs
|
||||||
|
|
||||||
|
# CA certs
|
||||||
|
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Setup the profiles for the Root CA, we will have 3 main profiles: one
|
||||||
|
for the clients connecting, one for the servers, and another one for
|
||||||
|
the full mesh routing connections between the servers.
|
||||||
|
|
||||||
|
```js :tangle certs/ca-config.json
|
||||||
|
{
|
||||||
|
"signing": {
|
||||||
|
"default": {
|
||||||
|
"expiry": "43800h"
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"server": {
|
||||||
|
"expiry": "43800h",
|
||||||
|
"usages": [
|
||||||
|
"signing",
|
||||||
|
"key encipherment",
|
||||||
|
"server auth",
|
||||||
|
"client auth"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"expiry": "43800h",
|
||||||
|
"usages": [
|
||||||
|
"signing",
|
||||||
|
"key encipherment",
|
||||||
|
"client auth"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"expiry": "43800h",
|
||||||
|
"usages": [
|
||||||
|
"signing",
|
||||||
|
"key encipherment",
|
||||||
|
"server auth",
|
||||||
|
"client auth"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Generating the NATS server certs
|
||||||
|
|
||||||
|
First we generate the certificates for the server.
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"CN": "nats.io",
|
||||||
|
"hosts": [
|
||||||
|
"localhost",
|
||||||
|
"*.nats-cluster.default.svc",
|
||||||
|
"*.nats-cluster-mgmt.default.svc",
|
||||||
|
"nats-cluster",
|
||||||
|
"nats-cluster-mgmt",
|
||||||
|
"nats-cluster.default.svc",
|
||||||
|
"nats-cluster-mgmt.default.svc",
|
||||||
|
"nats-cluster.default.svc.cluster.local",
|
||||||
|
"nats-cluster-mgmt.default.svc.cluster.local",
|
||||||
|
"*.nats-cluster.default.svc.cluster.local",
|
||||||
|
"*.nats-cluster-mgmt.default.svc.cluster.local"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"algo": "rsa",
|
||||||
|
"size": 2048
|
||||||
|
},
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"OU": "Operator"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
(
|
||||||
|
# Generating the peer certificates
|
||||||
|
cd certs
|
||||||
|
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Generating the NATS server routes certs
|
||||||
|
|
||||||
|
We will also be setting up TLS for the full mesh routes.
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"CN": "nats.io",
|
||||||
|
"hosts": [
|
||||||
|
"localhost",
|
||||||
|
"*.nats-cluster.default.svc",
|
||||||
|
"*.nats-cluster-mgmt.default.svc",
|
||||||
|
"nats-cluster",
|
||||||
|
"nats-cluster-mgmt",
|
||||||
|
"nats-cluster.default.svc",
|
||||||
|
"nats-cluster-mgmt.default.svc",
|
||||||
|
"nats-cluster.default.svc.cluster.local",
|
||||||
|
"nats-cluster-mgmt.default.svc.cluster.local",
|
||||||
|
"*.nats-cluster.default.svc.cluster.local",
|
||||||
|
"*.nats-cluster-mgmt.default.svc.cluster.local"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"algo": "rsa",
|
||||||
|
"size": 2048
|
||||||
|
},
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"OU": "Operator"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Generating the peer certificates
|
||||||
|
(
|
||||||
|
cd certs
|
||||||
|
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=route route.json | cfssljson -bare route
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Generating the certs for the clients (CNCF && ACME)
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"CN": "nats.io",
|
||||||
|
"hosts": [""],
|
||||||
|
"key": {
|
||||||
|
"algo": "rsa",
|
||||||
|
"size": 2048
|
||||||
|
},
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"OU": "CNCF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
(
|
||||||
|
cd certs
|
||||||
|
# Generating NATS client certs
|
||||||
|
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Kubectl create
|
||||||
|
|
||||||
|
```sh :results output
|
||||||
|
cd certs
|
||||||
|
kubectl create secret generic nats-tls-example --from-file=ca.pem --from-file=server-key.pem --from-file=server.pem
|
||||||
|
kubectl create secret generic nats-tls-routes-example --from-file=ca.pem --from-file=route-key.pem --from-file=route.pem
|
||||||
|
kubectl create secret generic nats-tls-client-example --from-file=ca.pem --from-file=client-key.pem --from-file=client.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create the Auth secret
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"users": [
|
||||||
|
{ "username": "CN=nats.io,OU=ACME" },
|
||||||
|
{ "username": "CN=nats.io,OU=CNCF",
|
||||||
|
"permissions": {
|
||||||
|
"publish": ["hello.*"],
|
||||||
|
"subscribe": ["hello.world"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_permissions": {
|
||||||
|
"publish": ["SANDBOX.*"],
|
||||||
|
"subscribe": ["PUBLIC.>"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl create secret generic nats-tls-users --from-file=users.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a cluster with TLS
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo '
|
||||||
|
apiVersion: "nats.io/v1alpha2"
|
||||||
|
kind: "NatsCluster"
|
||||||
|
metadata:
|
||||||
|
name: "nats-cluster"
|
||||||
|
spec:
|
||||||
|
size: 3
|
||||||
|
|
||||||
|
# Using custom edge nats server image for TLS verify and map support.
|
||||||
|
serverImage: "wallyqs/nats-server"
|
||||||
|
version: "edge-2.0.0-RC5"
|
||||||
|
|
||||||
|
tls:
|
||||||
|
enableHttps: true
|
||||||
|
|
||||||
|
# Certificates to secure the NATS client connections:
|
||||||
|
serverSecret: "nats-tls-example"
|
||||||
|
|
||||||
|
# Certificates to secure the routes.
|
||||||
|
routesSecret: "nats-tls-routes-example"
|
||||||
|
|
||||||
|
auth:
|
||||||
|
tlsVerifyAndMap: true
|
||||||
|
clientsAuthSecret: "nats-tls-users"
|
||||||
|
|
||||||
|
# How long to wait for authentication
|
||||||
|
clientsAuthTimeout: 5
|
||||||
|
|
||||||
|
pod:
|
||||||
|
# To be able to reload the secret changes
|
||||||
|
enableConfigReload: true
|
||||||
|
reloaderImage: connecteverything/nats-server-config-reloader
|
||||||
|
|
||||||
|
# Bind the port 4222 as the host port to allow external access.
|
||||||
|
enableClientsHostPort: true
|
||||||
|
|
||||||
|
# Initializer container that resolves the external IP from the
|
||||||
|
# container where it is running.
|
||||||
|
advertiseExternalIP: true
|
||||||
|
|
||||||
|
# Image of container that resolves external IP from K8S API
|
||||||
|
bootconfigImage: "wallyqs/nats-boot-config"
|
||||||
|
bootconfigImageTag: "0.5.0"
|
||||||
|
|
||||||
|
# Service account required to be able to find the external IP
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
serviceAccountName: "nats-server"
|
||||||
|
' | kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create APP using certs
|
||||||
|
|
||||||
|
#### Adding a new pod which uses the certificates
|
||||||
|
|
||||||
|
Development
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/nats-io/go-nats"
|
||||||
|
"github.com/nats-io/nuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
serverList string
|
||||||
|
rootCACertFile string
|
||||||
|
clientCertFile string
|
||||||
|
clientKeyFile string
|
||||||
|
)
|
||||||
|
flag.StringVar(&serverList, "s", "tls://nats-1.nats-cluster.default.svc:4222", "List of NATS of servers available")
|
||||||
|
flag.StringVar(&rootCACertFile, "cacert", "./certs/ca.pem", "Root CA Certificate File")
|
||||||
|
flag.StringVar(&clientCertFile, "cert", "./certs/client.pem", "Client Certificate File")
|
||||||
|
flag.StringVar(&clientKeyFile, "key", "./certs/client-key.pem", "Client Private key")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
log.Println("NATS endpoint:", serverList)
|
||||||
|
log.Println("Root CA:", rootCACertFile)
|
||||||
|
log.Println("Client Cert:", clientCertFile)
|
||||||
|
log.Println("Client Key:", clientKeyFile)
|
||||||
|
|
||||||
|
// Connect options
|
||||||
|
rootCA := nats.RootCAs(rootCACertFile)
|
||||||
|
clientCert := nats.ClientCert(clientCertFile, clientKeyFile)
|
||||||
|
alwaysReconnect := nats.MaxReconnects(-1)
|
||||||
|
|
||||||
|
var nc *nats.Conn
|
||||||
|
var err error
|
||||||
|
for {
|
||||||
|
nc, err = nats.Connect(serverList, rootCA, clientCert, alwaysReconnect)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error while connecting to NATS, backing off for a sec... (error: %s)", err)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
nc.Subscribe("discovery.*.status", func(m *nats.Msg) {
|
||||||
|
log.Printf("[Received on %q] %s", m.Subject, string(m.Data))
|
||||||
|
})
|
||||||
|
|
||||||
|
discoverySubject := fmt.Sprintf("discovery.%s.status", nuid.Next())
|
||||||
|
info := struct {
|
||||||
|
InMsgs uint64 `json:"in_msgs"`
|
||||||
|
OutMsgs uint64 `json:"out_msgs"`
|
||||||
|
Reconnects uint64 `json:"reconnects"`
|
||||||
|
CurrentServer string `json:"current_server"`
|
||||||
|
Servers []string `json:"servers"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
for range time.NewTicker(1 * time.Second).C {
|
||||||
|
stats := nc.Stats()
|
||||||
|
info.InMsgs = stats.InMsgs
|
||||||
|
info.OutMsgs = stats.OutMsgs
|
||||||
|
info.Reconnects = stats.Reconnects
|
||||||
|
info.CurrentServer = nc.ConnectedUrl()
|
||||||
|
info.Servers = nc.Servers()
|
||||||
|
payload, err := json.Marshal(info)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error marshalling data: %s", err)
|
||||||
|
}
|
||||||
|
err = nc.Publish(discoverySubject, payload)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error during publishing: %s", err)
|
||||||
|
}
|
||||||
|
nc.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
FROM golang:1.11.0-alpine3.8 AS builder
|
||||||
|
COPY . /go/src/github.com/nats-io/nats-kubernetes/examples/nats-cluster-routes-tls/app
|
||||||
|
WORKDIR /go/src/github.com/nats-io/nats-kubernetes/examples/nats-cluster-routes-tls/app
|
||||||
|
RUN apk add --update git
|
||||||
|
RUN go get -u github.com/nats-io/go-nats
|
||||||
|
RUN go get -u github.com/nats-io/nuid
|
||||||
|
RUN CGO_ENABLED=0 go build -o nats-client-app -v -a ./client.go
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=builder /go/src/github.com/nats-io/nats-kubernetes/examples/nats-cluster-routes-tls/app/nats-client-app /nats-client-app
|
||||||
|
ENTRYPOINT ["/nats-client-app"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker build . -t wallyqs/nats-client-app
|
||||||
|
docker run wallyqs/nats-client-app
|
||||||
|
docker push wallyqs/nats-client-app
|
||||||
|
```
|
||||||
|
Pod spec
|
||||||
|
|
||||||
|
```sh :results output
|
||||||
|
echo '
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
|
||||||
|
# The name of the deployment
|
||||||
|
metadata:
|
||||||
|
name: nats-client-app
|
||||||
|
|
||||||
|
spec:
|
||||||
|
# This selector has to match the template.metadata.labels section
|
||||||
|
# which is below in the PodSpec
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: nats-client-app
|
||||||
|
|
||||||
|
# Number of instances
|
||||||
|
replicas: 1
|
||||||
|
|
||||||
|
# PodSpec
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: nats-client-app
|
||||||
|
spec:
|
||||||
|
volumes:
|
||||||
|
- name: "client-tls-certs"
|
||||||
|
secret:
|
||||||
|
secretName: "nats-tls-client-example"
|
||||||
|
containers:
|
||||||
|
- name: nats-client-app
|
||||||
|
command: ["/nats-client-app", "-s", "tls://nats-cluster.default.svc:4222", "-cacert", '/etc/nats-client-tls-certs/ca.pem', '-cert', '/etc/nats-client-tls-certs/client.pem', '-key', '/etc/nats-client-tls-certs/client-key.pem']
|
||||||
|
image: wallyqs/nats-client-app:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
volumeMounts:
|
||||||
|
- name: "client-tls-certs"
|
||||||
|
mountPath: "/etc/nats-client-tls-certs/"
|
||||||
|
' | kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
297
nats-kubernetes/prometheus-and-nats-operator.md
Executable file
297
nats-kubernetes/prometheus-and-nats-operator.md
Executable file
@ -0,0 +1,297 @@
|
|||||||
|
|
||||||
|
# Prometheus Operator + NATS Operator
|
||||||
|
|
||||||
|
## Installing the Operators
|
||||||
|
|
||||||
|
Install the NATS Operator:
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
$ kubectl apply -f https://raw.githubusercontent.com/nats-io/nats-operator/master/deploy/00-prereqs.yaml
|
||||||
|
$ kubectl apply -f https://raw.githubusercontent.com/nats-io/nats-operator/master/deploy/10-deployment.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the Prometheus Operator along with its RBAC definition (prometheus-operator service account):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
app.kubernetes.io/version: v0.30.0
|
||||||
|
name: prometheus-operator
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: prometheus-operator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: prometheus-operator
|
||||||
|
namespace: default
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
app.kubernetes.io/version: v0.30.0
|
||||||
|
name: prometheus-operator
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- apiextensions.k8s.io
|
||||||
|
resources:
|
||||||
|
- customresourcedefinitions
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- monitoring.coreos.com
|
||||||
|
resources:
|
||||||
|
- alertmanagers
|
||||||
|
- prometheuses
|
||||||
|
- prometheuses/finalizers
|
||||||
|
- alertmanagers/finalizers
|
||||||
|
- servicemonitors
|
||||||
|
- podmonitors
|
||||||
|
- prometheusrules
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- statefulsets
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- services/finalizers
|
||||||
|
- endpoints
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- namespaces
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
app.kubernetes.io/version: v0.30.0
|
||||||
|
name: prometheus-operator
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
app.kubernetes.io/version: v0.30.0
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- args:
|
||||||
|
- --kubelet-service=kube-system/kubelet
|
||||||
|
- --logtostderr=true
|
||||||
|
- --config-reloader-image=quay.io/coreos/configmap-reload:v0.0.1
|
||||||
|
- --prometheus-config-reloader=quay.io/coreos/prometheus-config-reloader:v0.30.0
|
||||||
|
image: quay.io/coreos/prometheus-operator:v0.30.0
|
||||||
|
name: prometheus-operator
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 200Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
nodeSelector:
|
||||||
|
beta.kubernetes.io/os: linux
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 65534
|
||||||
|
serviceAccountName: prometheus-operator
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
app.kubernetes.io/version: v0.30.0
|
||||||
|
name: prometheus-operator
|
||||||
|
namespace: default
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
app.kubernetes.io/version: v0.30.0
|
||||||
|
name: prometheus-operator
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
clusterIP: None
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8080
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/component: controller
|
||||||
|
app.kubernetes.io/name: prometheus-operator
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create a NATS Cluster Instance
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: "nats.io/v1alpha2"
|
||||||
|
kind: "NatsCluster"
|
||||||
|
metadata:
|
||||||
|
name: "nats-cluster"
|
||||||
|
spec:
|
||||||
|
size: 3
|
||||||
|
version: "1.4.1"
|
||||||
|
pod:
|
||||||
|
enableMetrics: true
|
||||||
|
metricsImage: "synadia/prometheus-nats-exporter"
|
||||||
|
metricsImageTag: "0.3.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create a Prometheus instance
|
||||||
|
|
||||||
|
### Create RBAC for the Prometheus instance
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
- services
|
||||||
|
- endpoints
|
||||||
|
- pods
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs: ["get"]
|
||||||
|
- nonResourceURLs: ["/metrics"]
|
||||||
|
verbs: ["get"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: prometheus
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: prometheus
|
||||||
|
namespace: default
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create the Prometheus instance
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: Prometheus
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
spec:
|
||||||
|
serviceAccountName: prometheus
|
||||||
|
serviceMonitorSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: nats
|
||||||
|
nats_cluster: nats-cluster
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 400Mi
|
||||||
|
enableAdminAPI: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create the ServiceMonitor for the NATS cluster
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
name: nats-cluster
|
||||||
|
labels:
|
||||||
|
app: nats
|
||||||
|
nats_cluster: nats-cluster
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nats
|
||||||
|
nats_cluster: nats-cluster
|
||||||
|
endpoints:
|
||||||
|
- port: metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
## Confirm
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl port-forward prometheus-prometheus-0 9090:9090
|
||||||
|
```
|
||||||
|
|
||||||
|
Results:
|
||||||
|
|
||||||
|
<img height="400" width="1000" src="https://user-images.githubusercontent.com/26195/59470419-2066fd80-8e27-11e9-9e3e-250296a091da.png">
|
||||||
|
|
||||||
|
|
||||||
|
|
390
nats-kubernetes/stan-ft-k8s-aws.md
Normal file
390
nats-kubernetes/stan-ft-k8s-aws.md
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
# Creating a NATS Streaming cluster in K8S with FT mode
|
||||||
|
|
||||||
|
## Preparation
|
||||||
|
|
||||||
|
First, we need a Kubernetes cluster with a provider that offers a
|
||||||
|
service with a `ReadWriteMany` filesystem available. In this short guide,
|
||||||
|
we will create the cluster on AWS and then use EFS for the filesystem:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create 3 nodes Kubernetes cluster
|
||||||
|
eksctl create cluster --name nats-eks-cluster \
|
||||||
|
--nodes 3 \
|
||||||
|
--node-type=t3.large \
|
||||||
|
--region=us-east-2
|
||||||
|
|
||||||
|
# Get the credentials for your cluster
|
||||||
|
eksctl utils write-kubeconfig --name nats-eks-cluster --region us-east-2
|
||||||
|
```
|
||||||
|
|
||||||
|
For the FT mode to work, we will need to create an EFS volume which
|
||||||
|
can be shared by more than one pod. Go into the [AWS console](https://us-east-2.console.aws.amazon.com/efs/home?region=us-east-2#/wizard/1) and create one and make the sure that it is in a security group where the k8s nodes will have access to it. In case of clusters created via eksctl, this will be a security group named `ClusterSharedNodeSecurityGroup`:
|
||||||
|
|
||||||
|
<img width="1063" alt="Screen Shot 2019-12-04 at 11 25 08 AM" src="https://user-images.githubusercontent.com/26195/70177488-5ef0bd00-16d2-11ea-9cf3-e0c3196bc7da.png">
|
||||||
|
|
||||||
|
<img width="1177" alt="Screen Shot 2019-12-04 at 12 40 13 PM" src="https://user-images.githubusercontent.com/26195/70179769-9497a500-16d6-11ea-9e18-2a8588a71819.png">
|
||||||
|
|
||||||
|
### Creating the EFS provisioner
|
||||||
|
|
||||||
|
Confirm from the FilesystemID from the cluster and the DNS name, we will use those values to create an EFS provisioner controller within the K8S cluster:
|
||||||
|
|
||||||
|
<img width="852" alt="Screen Shot 2019-12-04 at 12 08 35 PM" src="https://user-images.githubusercontent.com/26195/70177502-657f3480-16d2-11ea-9d00-b9a8c2f5320b.png">
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: efs-provisioner
|
||||||
|
---
|
||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: efs-provisioner-runner
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumes"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "delete"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims"]
|
||||||
|
verbs: ["get", "list", "watch", "update"]
|
||||||
|
- apiGroups: ["storage.k8s.io"]
|
||||||
|
resources: ["storageclasses"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["events"]
|
||||||
|
verbs: ["create", "update", "patch"]
|
||||||
|
---
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: run-efs-provisioner
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: efs-provisioner
|
||||||
|
# replace with namespace where provisioner is deployed
|
||||||
|
namespace: default
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: efs-provisioner-runner
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: leader-locking-efs-provisioner
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["endpoints"]
|
||||||
|
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: leader-locking-efs-provisioner
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: efs-provisioner
|
||||||
|
# replace with namespace where provisioner is deployed
|
||||||
|
namespace: default
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: leader-locking-efs-provisioner
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: efs-provisioner
|
||||||
|
data:
|
||||||
|
file.system.id: fs-c22a24bb
|
||||||
|
aws.region: us-east-2
|
||||||
|
provisioner.name: synadia.com/aws-efs
|
||||||
|
dns.name: ""
|
||||||
|
---
|
||||||
|
kind: Deployment
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: efs-provisioner
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: efs-provisioner
|
||||||
|
spec:
|
||||||
|
serviceAccountName: efs-provisioner
|
||||||
|
containers:
|
||||||
|
- name: efs-provisioner
|
||||||
|
image: quay.io/external_storage/efs-provisioner:latest
|
||||||
|
env:
|
||||||
|
- name: FILE_SYSTEM_ID
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: efs-provisioner
|
||||||
|
key: file.system.id
|
||||||
|
- name: AWS_REGION
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: efs-provisioner
|
||||||
|
key: aws.region
|
||||||
|
- name: DNS_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: efs-provisioner
|
||||||
|
key: dns.name
|
||||||
|
|
||||||
|
- name: PROVISIONER_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: efs-provisioner
|
||||||
|
key: provisioner.name
|
||||||
|
volumeMounts:
|
||||||
|
- name: pv-volume
|
||||||
|
mountPath: /efs
|
||||||
|
volumes:
|
||||||
|
- name: pv-volume
|
||||||
|
nfs:
|
||||||
|
server: fs-c22a24bb.efs.us-east-2.amazonaws.com
|
||||||
|
path: /
|
||||||
|
---
|
||||||
|
kind: StorageClass
|
||||||
|
apiVersion: storage.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: aws-efs
|
||||||
|
provisioner: synadia.com/aws-efs
|
||||||
|
---
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: efs
|
||||||
|
annotations:
|
||||||
|
volume.beta.kubernetes.io/storage-class: "aws-efs"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Mi
|
||||||
|
```
|
||||||
|
|
||||||
|
Result of deploying the manifest:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
serviceaccount/efs-provisioner created
|
||||||
|
clusterrole.rbac.authorization.k8s.io/efs-provisioner-runner created
|
||||||
|
clusterrolebinding.rbac.authorization.k8s.io/run-efs-provisioner created
|
||||||
|
role.rbac.authorization.k8s.io/leader-locking-efs-provisioner created
|
||||||
|
rolebinding.rbac.authorization.k8s.io/leader-locking-efs-provisioner created
|
||||||
|
configmap/efs-provisioner created
|
||||||
|
deployment.extensions/efs-provisioner created
|
||||||
|
storageclass.storage.k8s.io/aws-efs created
|
||||||
|
persistentvolumeclaim/efs created
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting up the NATS Streaming cluster
|
||||||
|
|
||||||
|
Now create a NATS Streaming cluster with FT mode enabled and using NATS embedded mode
|
||||||
|
that is mounting the EFS volume:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: stan
|
||||||
|
labels:
|
||||||
|
app: stan
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: stan
|
||||||
|
clusterIP: None
|
||||||
|
ports:
|
||||||
|
- name: client
|
||||||
|
port: 4222
|
||||||
|
- name: cluster
|
||||||
|
port: 6222
|
||||||
|
- name: monitor
|
||||||
|
port: 8222
|
||||||
|
- name: metrics
|
||||||
|
port: 7777
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: stan-config
|
||||||
|
data:
|
||||||
|
stan.conf: |
|
||||||
|
http: 8222
|
||||||
|
|
||||||
|
cluster {
|
||||||
|
port: 6222
|
||||||
|
routes [
|
||||||
|
nats://stan:6222
|
||||||
|
]
|
||||||
|
cluster_advertise: $CLUSTER_ADVERTISE
|
||||||
|
connect_retries: 10
|
||||||
|
}
|
||||||
|
streaming {
|
||||||
|
id: test-cluster
|
||||||
|
store: file
|
||||||
|
dir: /data/stan/store
|
||||||
|
ft_group_name: "test-cluster"
|
||||||
|
file_options {
|
||||||
|
buffer_size: 32mb
|
||||||
|
sync_on_flush: false
|
||||||
|
slice_max_bytes: 512mb
|
||||||
|
parallel_recovery: 64
|
||||||
|
}
|
||||||
|
store_limits {
|
||||||
|
max_channels: 10
|
||||||
|
max_msgs: 0
|
||||||
|
max_bytes: 256gb
|
||||||
|
max_age: 1h
|
||||||
|
max_subs: 128
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: stan
|
||||||
|
labels:
|
||||||
|
app: stan
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: stan
|
||||||
|
serviceName: stan
|
||||||
|
replicas: 3
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: efs
|
||||||
|
annotations:
|
||||||
|
volume.beta.kubernetes.io/storage-class: "aws-efs"
|
||||||
|
spec:
|
||||||
|
accessModes: [ "ReadWriteMany" ]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Mi
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: stan
|
||||||
|
spec:
|
||||||
|
# STAN Server
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
|
||||||
|
containers:
|
||||||
|
- name: stan
|
||||||
|
image: nats-streaming:latest
|
||||||
|
|
||||||
|
ports:
|
||||||
|
# In case of NATS embedded mode expose these ports
|
||||||
|
- containerPort: 4222
|
||||||
|
name: client
|
||||||
|
- containerPort: 6222
|
||||||
|
name: cluster
|
||||||
|
- containerPort: 8222
|
||||||
|
name: monitor
|
||||||
|
args:
|
||||||
|
- "-sc"
|
||||||
|
- "/etc/stan-config/stan.conf"
|
||||||
|
|
||||||
|
# Required to be able to define an environment variable
|
||||||
|
# that refers to other environment variables. This env var
|
||||||
|
# is later used as part of the configuration file.
|
||||||
|
env:
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
- name: CLUSTER_ADVERTISE
|
||||||
|
value: $(POD_NAME).stan.$(POD_NAMESPACE).svc
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /etc/stan-config
|
||||||
|
- name: efs
|
||||||
|
mountPath: /data/stan
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 0
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 8222
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
- name: metrics
|
||||||
|
image: synadia/prometheus-nats-exporter:0.5.0
|
||||||
|
args:
|
||||||
|
- -connz
|
||||||
|
- -routez
|
||||||
|
- -subz
|
||||||
|
- -varz
|
||||||
|
- -channelz
|
||||||
|
- -serverz
|
||||||
|
- http://localhost:8222
|
||||||
|
ports:
|
||||||
|
- containerPort: 7777
|
||||||
|
name: metrics
|
||||||
|
volumes:
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: stan-config
|
||||||
|
```
|
||||||
|
|
||||||
|
Your cluster now will look something like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl get pods
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
efs-provisioner-6b7866dd4-4k5wx 1/1 Running 0 21m
|
||||||
|
stan-0 2/2 Running 0 6m35s
|
||||||
|
stan-1 2/2 Running 0 4m56s
|
||||||
|
stan-2 2/2 Running 0 4m42s
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything was setup properly, one of the servers will be the active node.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ kubectl logs stan-0 -c stan
|
||||||
|
[1] 2019/12/04 20:40:40.429359 [INF] STREAM: Starting nats-streaming-server[test-cluster] version 0.16.2
|
||||||
|
[1] 2019/12/04 20:40:40.429385 [INF] STREAM: ServerID: 7j3t3Ii7e2tifWqanYKwFX
|
||||||
|
[1] 2019/12/04 20:40:40.429389 [INF] STREAM: Go version: go1.11.13
|
||||||
|
[1] 2019/12/04 20:40:40.429392 [INF] STREAM: Git commit: [910d6e1]
|
||||||
|
[1] 2019/12/04 20:40:40.454212 [INF] Starting nats-server version 2.0.4
|
||||||
|
[1] 2019/12/04 20:40:40.454360 [INF] Git commit [c8ca58e]
|
||||||
|
[1] 2019/12/04 20:40:40.454522 [INF] Starting http monitor on 0.0.0.0:8222
|
||||||
|
[1] 2019/12/04 20:40:40.454830 [INF] Listening for client connections on 0.0.0.0:4222
|
||||||
|
[1] 2019/12/04 20:40:40.454841 [INF] Server id is NB3A5RSGABLJP3WUYG6VYA36ZGE7MP5GVQIQVRG6WUYSRJA7B2NNMW57
|
||||||
|
[1] 2019/12/04 20:40:40.454844 [INF] Server is ready
|
||||||
|
[1] 2019/12/04 20:40:40.456360 [INF] Listening for route connections on 0.0.0.0:6222
|
||||||
|
[1] 2019/12/04 20:40:40.481927 [INF] STREAM: Starting in standby mode
|
||||||
|
[1] 2019/12/04 20:40:40.488193 [ERR] Error trying to connect to route (attempt 1): dial tcp: lookup stan on 10.100.0.10:53: no such host
|
||||||
|
[1] 2019/12/04 20:40:41.489688 [INF] 192.168.52.76:40992 - rid:6 - Route connection created
|
||||||
|
[1] 2019/12/04 20:40:41.489788 [INF] 192.168.52.76:40992 - rid:6 - Router connection closed
|
||||||
|
[1] 2019/12/04 20:40:41.489695 [INF] 192.168.52.76:6222 - rid:5 - Route connection created
|
||||||
|
[1] 2019/12/04 20:40:41.489955 [INF] 192.168.52.76:6222 - rid:5 - Router connection closed
|
||||||
|
[1] 2019/12/04 20:40:41.634944 [INF] STREAM: Server is active
|
||||||
|
[1] 2019/12/04 20:40:41.634976 [INF] STREAM: Recovering the state...
|
||||||
|
[1] 2019/12/04 20:40:41.655526 [INF] STREAM: No recovered state
|
||||||
|
[1] 2019/12/04 20:40:41.671435 [INF] STREAM: Message store is FILE
|
||||||
|
[1] 2019/12/04 20:40:41.671448 [INF] STREAM: Store location: /data/stan/store
|
||||||
|
[1] 2019/12/04 20:40:41.671524 [INF] STREAM: ---------- Store Limits ----------
|
||||||
|
[1] 2019/12/04 20:40:41.671527 [INF] STREAM: Channels: 10
|
||||||
|
[1] 2019/12/04 20:40:41.671529 [INF] STREAM: --------- Channels Limits --------
|
||||||
|
[1] 2019/12/04 20:40:41.671531 [INF] STREAM: Subscriptions: 128
|
||||||
|
[1] 2019/12/04 20:40:41.671533 [INF] STREAM: Messages : unlimited
|
||||||
|
[1] 2019/12/04 20:40:41.671535 [INF] STREAM: Bytes : 256.00 GB
|
||||||
|
[1] 2019/12/04 20:40:41.671537 [INF] STREAM: Age : 1h0m0s
|
||||||
|
[1] 2019/12/04 20:40:41.671539 [INF] STREAM: Inactivity : unlimited *
|
||||||
|
[1] 2019/12/04 20:40:41.671541 [INF] STREAM: ----------------------------------
|
||||||
|
[1] 2019/12/04 20:40:41.671546 [INF] STREAM: Streaming Server is ready
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user