From ae8d6a6cf36219ee34181d409048e68e31aab9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Wed, 5 Jun 2019 17:57:16 +0200 Subject: [PATCH 1/5] WIP: Set up ingress with Let's Encrypt certificates using cert-manager This is using haproxy-ingress to support forwarding SSH on port 22 Since we're using cert-manager with ingress to get Let's Encrypt certs, we're not using the Let's Encrypt functionality that's part of Gitea. To run this we need to change the config file, have Gitea run on port 3000 as HTTP and disable all the Let's Encrypt config keys. Currently the gitea-ingress.yaml uses the letsencrypt-staging ClusterIssuer This has been tested on a local Kubernetes cluster using Docker for Mac --- kubernetes/cert-manager.yaml | 1791 ++++++++++++++++++++++++ kubernetes/gitea-ingress.yaml | 276 ++++ kubernetes/gitea-server.yaml | 18 +- kubernetes/letsencrypt-production.yaml | 19 + kubernetes/letsencrypt-staging.yaml | 19 + 5 files changed, 2119 insertions(+), 4 deletions(-) create mode 100644 kubernetes/cert-manager.yaml create mode 100644 kubernetes/gitea-ingress.yaml create mode 100644 kubernetes/letsencrypt-production.yaml create mode 100644 kubernetes/letsencrypt-staging.yaml diff --git a/kubernetes/cert-manager.yaml b/kubernetes/cert-manager.yaml new file mode 100644 index 0000000..69638aa --- /dev/null +++ b/kubernetes/cert-manager.yaml @@ -0,0 +1,1791 @@ +# cert-manager docs are at https://cert-manager.readthedocs.io/en/latest/getting-started/install/kubernetes.html +# This file was copied from https://github.com/jetstack/cert-manager/releases/download/v0.8.0/cert-manager.yaml +# It must be applied with `kubectl apply -f cert-manager.yaml --validate=false` +# on Kubernetes < 1.13 +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + labels: + controller-tools.k8s.io: "1.0" + name: certificates.certmanager.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - JSONPath: .spec.secretName + name: Secret + type: string + - JSONPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - JSONPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - JSONPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. + name: Age + type: date + group: certmanager.k8s.io + names: + kind: Certificate + plural: certificates + shortNames: + - cert + - certs + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + acme: + description: ACME contains configuration specific to ACME Certificates. + Notably, this contains details on how the domain names listed on this + Certificate resource should be 'solved', i.e. mapping HTTP01 and DNS01 + providers to DNS names. + properties: + config: + items: + properties: + domains: + description: Domains is the list of domains that this SolverConfig + applies to. + items: + type: string + type: array + required: + - domains + type: object + type: array + required: + - config + type: object + commonName: + description: CommonName is a common name to be used on the Certificate + type: string + dnsNames: + description: DNSNames is a list of subject alt names to be used on the + Certificate + items: + type: string + type: array + duration: + description: Certificate default Duration + type: string + ipAddresses: + description: IPAddresses is a list of IP addresses to be used on the + Certificate + items: + type: string + type: array + isCA: + description: IsCA will mark this Certificate as valid for signing. This + implies that the 'signing' usage is set + type: boolean + issuerRef: + description: IssuerRef is a reference to the issuer for this certificate. + If the 'kind' field is not set, or set to 'Issuer', an Issuer resource + with the given name in the same namespace as the Certificate will + be used. If the 'kind' field is set to 'ClusterIssuer', a ClusterIssuer + with the provided name will be used. The 'name' field in this stanza + is required at all times. + properties: + kind: + type: string + name: + type: string + required: + - name + type: object + keyAlgorithm: + description: KeyAlgorithm is the private key algorithm of the corresponding + private key for this certificate. If provided, allowed values are + either "rsa" or "ecdsa" If KeyAlgorithm is specified and KeySize is + not provided, key size of 256 will be used for "ecdsa" key algorithm + and key size of 2048 will be used for "rsa" key algorithm. + enum: + - rsa + - ecdsa + type: string + keySize: + description: KeySize is the key bit size of the corresponding private + key for this certificate. If provided, value must be between 2048 + and 8192 inclusive when KeyAlgorithm is empty or is set to "rsa", + and value must be one of (256, 384, 521) when KeyAlgorithm is set + to "ecdsa". + format: int64 + type: integer + organization: + description: Organization is the organization to be used on the Certificate + items: + type: string + type: array + renewBefore: + description: Certificate renew before expiration duration + type: string + secretName: + description: SecretName is the name of the secret resource to store + this secret in + type: string + required: + - secretName + - issuerRef + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding + to the last status change of this condition. + format: date-time + type: string + message: + description: Message is a human readable description of the details + of the last transition, complementing reason. + type: string + reason: + description: Reason is a brief machine readable explanation for + the condition's last transition. + type: string + status: + description: Status of the condition, one of ('True', 'False', + 'Unknown'). + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: Type of the condition, currently ('Ready'). + type: string + required: + - type + - status + type: object + type: array + lastFailureTime: + format: date-time + type: string + notAfter: + description: The expiration time of the certificate stored in the secret + named by this resource in spec.secretName. + format: date-time + type: string + type: object + version: v1alpha1 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + labels: + controller-tools.k8s.io: "1.0" + name: challenges.certmanager.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.state + name: State + type: string + - JSONPath: .spec.dnsName + name: Domain + type: string + - JSONPath: .status.reason + name: Reason + priority: 1 + type: string + - JSONPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. + name: Age + type: date + group: certmanager.k8s.io + names: + kind: Challenge + plural: challenges + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + authzURL: + description: AuthzURL is the URL to the ACME Authorization resource + that this challenge is a part of. + type: string + config: + description: 'Config specifies the solver configuration for this challenge. + Only **one** of ''config'' or ''solver'' may be specified, and if + both are specified then no action will be performed on the Challenge + resource. DEPRECATED: the ''solver'' field should be specified instead' + type: object + dnsName: + description: DNSName is the identifier that this challenge is for, e.g. + example.com. + type: string + issuerRef: + description: IssuerRef references a properly configured ACME-type Issuer + which should be used to create this Challenge. If the Issuer does + not exist, processing will be retried. If the Issuer is not an 'ACME' + Issuer, an error will be returned and the Challenge will be marked + as failed. + properties: + kind: + type: string + name: + type: string + required: + - name + type: object + key: + description: Key is the ACME challenge key for this challenge + type: string + solver: + description: Solver contains the domain solving configuration that should + be used to solve this challenge resource. Only **one** of 'config' + or 'solver' may be specified, and if both are specified then no action + will be performed on the Challenge resource. + properties: + selector: + description: Selector selects a set of DNSNames on the Certificate + resource that should be solved using this challenge solver. + properties: + dnsNames: + description: List of DNSNames that can be used to further refine + the domains that this solver applies to. + items: + type: string + type: array + matchLabels: + description: 'A label selector that is used to refine the set + of certificate''s that this challenge solver will apply to. + TODO: use kubernetes standard types for matchLabels' + type: object + type: object + type: object + token: + description: Token is the ACME challenge token for this challenge. + type: string + type: + description: Type is the type of ACME challenge this resource represents, + e.g. "dns01" or "http01" + type: string + url: + description: URL is the URL of the ACME Challenge resource for this + challenge. This can be used to lookup details about the status of + this challenge. + type: string + wildcard: + description: Wildcard will be true if this challenge is for a wildcard + identifier, for example '*.example.com' + type: boolean + required: + - authzURL + - type + - url + - dnsName + - token + - key + - wildcard + - issuerRef + type: object + status: + properties: + presented: + description: Presented will be set to true if the challenge values for + this challenge are currently 'presented'. This *does not* imply the + self check is passing. Only that the values have been 'submitted' + for the appropriate challenge mechanism (i.e. the DNS01 TXT record + has been presented, or the HTTP01 configuration has been configured). + type: boolean + processing: + description: Processing is used to denote whether this challenge should + be processed or not. This field will only be set to true by the 'scheduling' + component. It will only be set to false by the 'challenges' controller, + after the challenge has reached a final state or timed out. If this + field is set to false, the challenge controller will not take any + more action. + type: boolean + reason: + description: Reason contains human readable information on why the Challenge + is in the current state. + type: string + state: + description: State contains the current 'state' of the challenge. If + not set, the state of the challenge is unknown. + enum: + - "" + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + type: string + required: + - processing + - presented + - reason + type: object + required: + - metadata + - spec + - status + version: v1alpha1 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + labels: + controller-tools.k8s.io: "1.0" + name: clusterissuers.certmanager.k8s.io +spec: + group: certmanager.k8s.io + names: + kind: ClusterIssuer + plural: clusterissuers + scope: Cluster + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + acme: + properties: + email: + description: Email is the email for this account + type: string + privateKeySecretRef: + description: PrivateKey is the name of a secret containing the private + key for this user account. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + server: + description: Server is the ACME server URL + type: string + skipTLSVerify: + description: If true, skip verifying the ACME server TLS certificate + type: boolean + solvers: + description: Solvers is a list of challenge solvers that will be + used to solve ACME challenges for the matching domains. + items: + properties: + selector: + description: Selector selects a set of DNSNames on the Certificate + resource that should be solved using this challenge solver. + properties: + dnsNames: + description: List of DNSNames that can be used to further + refine the domains that this solver applies to. + items: + type: string + type: array + matchLabels: + description: 'A label selector that is used to refine + the set of certificate''s that this challenge solver + will apply to. TODO: use kubernetes standard types for + matchLabels' + type: object + type: object + type: object + type: array + required: + - server + - privateKeySecretRef + type: object + ca: + properties: + secretName: + description: SecretName is the name of the secret used to sign Certificates + issued by this Issuer. + type: string + required: + - secretName + type: object + selfSigned: + type: object + vault: + properties: + auth: + description: Vault authentication + properties: + appRole: + description: This Secret contains a AppRole and Secret + properties: + path: + description: Where the authentication path is mounted in + Vault. + type: string + roleId: + type: string + secretRef: + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + required: + - path + - roleId + - secretRef + type: object + tokenSecretRef: + description: This Secret contains the Vault token key + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + type: object + caBundle: + description: Base64 encoded CA bundle to validate Vault server certificate. + Only used if the Server URL is using HTTPS protocol. This parameter + is ignored for plain HTTP protocol connection. If not set the + system root certificates are used to validate the TLS connection. + format: byte + type: string + path: + description: Vault URL path to the certificate role + type: string + server: + description: Server is the vault connection address + type: string + required: + - auth + - server + - path + type: object + venafi: + properties: + cloud: + description: Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for + the Venafi Cloud API token. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + url: + description: URL is the base URL for Venafi Cloud + type: string + required: + - url + - apiTokenSecretRef + type: object + tpp: + description: TPP specifies Trust Protection Platform configuration + settings. Only one of TPP or Cloud may be specified. + properties: + caBundle: + description: CABundle is a PEM encoded TLS certifiate to use + to verify connections to the TPP instance. If specified, system + roots will not be used and the issuing CA for the TPP instance + must be verifiable using the provided root. If not specified, + the connection will be verified using the cert-manager system + root certificates. + format: byte + type: string + credentialsRef: + description: CredentialsRef is a reference to a Secret containing + the username and password for the TPP server. The secret must + contain two keys, 'username' and 'password'. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + url: + description: URL is the base URL for the Venafi TPP instance + type: string + required: + - url + - credentialsRef + type: object + zone: + description: Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by + the named zone policy. This field is required. + type: string + required: + - zone + type: object + type: object + status: + properties: + acme: + properties: + uri: + description: URI is the unique account identifier, which can also + be used to retrieve account details from the CA + type: string + type: object + conditions: + items: + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding + to the last status change of this condition. + format: date-time + type: string + message: + description: Message is a human readable description of the details + of the last transition, complementing reason. + type: string + reason: + description: Reason is a brief machine readable explanation for + the condition's last transition. + type: string + status: + description: Status of the condition, one of ('True', 'False', + 'Unknown'). + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: Type of the condition, currently ('Ready'). + type: string + required: + - type + - status + type: object + type: array + type: object + version: v1alpha1 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + labels: + controller-tools.k8s.io: "1.0" + name: issuers.certmanager.k8s.io +spec: + group: certmanager.k8s.io + names: + kind: Issuer + plural: issuers + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + acme: + properties: + email: + description: Email is the email for this account + type: string + privateKeySecretRef: + description: PrivateKey is the name of a secret containing the private + key for this user account. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + server: + description: Server is the ACME server URL + type: string + skipTLSVerify: + description: If true, skip verifying the ACME server TLS certificate + type: boolean + solvers: + description: Solvers is a list of challenge solvers that will be + used to solve ACME challenges for the matching domains. + items: + properties: + selector: + description: Selector selects a set of DNSNames on the Certificate + resource that should be solved using this challenge solver. + properties: + dnsNames: + description: List of DNSNames that can be used to further + refine the domains that this solver applies to. + items: + type: string + type: array + matchLabels: + description: 'A label selector that is used to refine + the set of certificate''s that this challenge solver + will apply to. TODO: use kubernetes standard types for + matchLabels' + type: object + type: object + type: object + type: array + required: + - server + - privateKeySecretRef + type: object + ca: + properties: + secretName: + description: SecretName is the name of the secret used to sign Certificates + issued by this Issuer. + type: string + required: + - secretName + type: object + selfSigned: + type: object + vault: + properties: + auth: + description: Vault authentication + properties: + appRole: + description: This Secret contains a AppRole and Secret + properties: + path: + description: Where the authentication path is mounted in + Vault. + type: string + roleId: + type: string + secretRef: + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + required: + - path + - roleId + - secretRef + type: object + tokenSecretRef: + description: This Secret contains the Vault token key + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + type: object + caBundle: + description: Base64 encoded CA bundle to validate Vault server certificate. + Only used if the Server URL is using HTTPS protocol. This parameter + is ignored for plain HTTP protocol connection. If not set the + system root certificates are used to validate the TLS connection. + format: byte + type: string + path: + description: Vault URL path to the certificate role + type: string + server: + description: Server is the vault connection address + type: string + required: + - auth + - server + - path + type: object + venafi: + properties: + cloud: + description: Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for + the Venafi Cloud API token. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + url: + description: URL is the base URL for Venafi Cloud + type: string + required: + - url + - apiTokenSecretRef + type: object + tpp: + description: TPP specifies Trust Protection Platform configuration + settings. Only one of TPP or Cloud may be specified. + properties: + caBundle: + description: CABundle is a PEM encoded TLS certifiate to use + to verify connections to the TPP instance. If specified, system + roots will not be used and the issuing CA for the TPP instance + must be verifiable using the provided root. If not specified, + the connection will be verified using the cert-manager system + root certificates. + format: byte + type: string + credentialsRef: + description: CredentialsRef is a reference to a Secret containing + the username and password for the TPP server. The secret must + contain two keys, 'username' and 'password'. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + required: + - name + type: object + url: + description: URL is the base URL for the Venafi TPP instance + type: string + required: + - url + - credentialsRef + type: object + zone: + description: Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by + the named zone policy. This field is required. + type: string + required: + - zone + type: object + type: object + status: + properties: + acme: + properties: + uri: + description: URI is the unique account identifier, which can also + be used to retrieve account details from the CA + type: string + type: object + conditions: + items: + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding + to the last status change of this condition. + format: date-time + type: string + message: + description: Message is a human readable description of the details + of the last transition, complementing reason. + type: string + reason: + description: Reason is a brief machine readable explanation for + the condition's last transition. + type: string + status: + description: Status of the condition, one of ('True', 'False', + 'Unknown'). + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: Type of the condition, currently ('Ready'). + type: string + required: + - type + - status + type: object + type: array + type: object + version: v1alpha1 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + labels: + controller-tools.k8s.io: "1.0" + name: orders.certmanager.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.state + name: State + type: string + - JSONPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - JSONPath: .status.reason + name: Reason + priority: 1 + type: string + - JSONPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. + name: Age + type: date + group: certmanager.k8s.io + names: + kind: Order + plural: orders + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + commonName: + description: CommonName is the common name as specified on the DER encoded + CSR. If CommonName is not specified, the first DNSName specified will + be used as the CommonName. At least one of CommonName or a DNSNames + must be set. This field must match the corresponding field on the + DER encoded CSR. + type: string + config: + description: 'Config specifies a mapping from DNS identifiers to how + those identifiers should be solved when performing ACME challenges. + A config entry must exist for each domain listed in DNSNames and CommonName. + Only **one** of ''config'' or ''solvers'' may be specified, and if + both are specified then no action will be performed on the Order resource. This + field will be removed when support for solver config specified on + the Certificate under certificate.spec.acme has been removed. DEPRECATED: + this field will be removed in future. Solver configuration must instead + be provided on ACME Issuer resources.' + items: + properties: + domains: + description: Domains is the list of domains that this SolverConfig + applies to. + items: + type: string + type: array + required: + - domains + type: object + type: array + csr: + description: Certificate signing request bytes in DER encoding. This + will be used when finalizing the order. This field must be set on + the order. + format: byte + type: string + dnsNames: + description: DNSNames is a list of DNS names that should be included + as part of the Order validation process. If CommonName is not specified, + the first DNSName specified will be used as the CommonName. At least + one of CommonName or a DNSNames must be set. This field must match + the corresponding field on the DER encoded CSR. + items: + type: string + type: array + issuerRef: + description: IssuerRef references a properly configured ACME-type Issuer + which should be used to create this Order. If the Issuer does not + exist, processing will be retried. If the Issuer is not an 'ACME' + Issuer, an error will be returned and the Order will be marked as + failed. + properties: + kind: + type: string + name: + type: string + required: + - name + type: object + required: + - csr + - issuerRef + type: object + status: + properties: + certificate: + description: Certificate is a copy of the PEM encoded certificate for + this Order. This field will be populated after the order has been + successfully finalized with the ACME server, and the order has transitioned + to the 'valid' state. + format: byte + type: string + challenges: + description: Challenges is a list of ChallengeSpecs for Challenges that + must be created in order to complete this Order. + items: + properties: + authzURL: + description: AuthzURL is the URL to the ACME Authorization resource + that this challenge is a part of. + type: string + config: + description: 'Config specifies the solver configuration for this + challenge. Only **one** of ''config'' or ''solver'' may be specified, + and if both are specified then no action will be performed on + the Challenge resource. DEPRECATED: the ''solver'' field should + be specified instead' + type: object + dnsName: + description: DNSName is the identifier that this challenge is + for, e.g. example.com. + type: string + issuerRef: + description: IssuerRef references a properly configured ACME-type + Issuer which should be used to create this Challenge. If the + Issuer does not exist, processing will be retried. If the Issuer + is not an 'ACME' Issuer, an error will be returned and the Challenge + will be marked as failed. + properties: + kind: + type: string + name: + type: string + required: + - name + type: object + key: + description: Key is the ACME challenge key for this challenge + type: string + solver: + description: Solver contains the domain solving configuration + that should be used to solve this challenge resource. Only **one** + of 'config' or 'solver' may be specified, and if both are specified + then no action will be performed on the Challenge resource. + properties: + selector: + description: Selector selects a set of DNSNames on the Certificate + resource that should be solved using this challenge solver. + properties: + dnsNames: + description: List of DNSNames that can be used to further + refine the domains that this solver applies to. + items: + type: string + type: array + matchLabels: + description: 'A label selector that is used to refine + the set of certificate''s that this challenge solver + will apply to. TODO: use kubernetes standard types for + matchLabels' + type: object + type: object + type: object + token: + description: Token is the ACME challenge token for this challenge. + type: string + type: + description: Type is the type of ACME challenge this resource + represents, e.g. "dns01" or "http01" + type: string + url: + description: URL is the URL of the ACME Challenge resource for + this challenge. This can be used to lookup details about the + status of this challenge. + type: string + wildcard: + description: Wildcard will be true if this challenge is for a + wildcard identifier, for example '*.example.com' + type: boolean + required: + - authzURL + - type + - url + - dnsName + - token + - key + - wildcard + - issuerRef + type: object + type: array + failureTime: + description: FailureTime stores the time that this order failed. This + is used to influence garbage collection and back-off. + format: date-time + type: string + finalizeURL: + description: FinalizeURL of the Order. This is used to obtain certificates + for this order once it has been completed. + type: string + reason: + description: Reason optionally provides more information about a why + the order is in the current state. + type: string + state: + description: State contains the current state of this Order resource. + States 'success' and 'expired' are 'final' + enum: + - "" + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + type: string + url: + description: URL of the Order. This will initially be empty when the + resource is first created. The Order controller will populate this + field when the Order is first processed. This field will be immutable + after it is initially set. + type: string + type: object + required: + - metadata + - spec + - status + version: v1alpha1 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cert-manager + labels: + certmanager.k8s.io/disable-validation: "true" + +--- +--- +# Source: cert-manager/charts/cainjector/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cert-manager-cainjector + namespace: "cert-manager" + labels: + app: cainjector + chart: cainjector-v0.8.0 + release: cert-manager + heritage: Tiller + +--- +# Source: cert-manager/charts/webhook/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cert-manager-webhook + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller + +--- +# Source: cert-manager/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cert-manager + namespace: "cert-manager" + labels: + app: cert-manager + chart: cert-manager-v0.8.0 + release: cert-manager + heritage: Tiller + +--- +# Source: cert-manager/charts/cainjector/templates/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: cert-manager-cainjector + labels: + app: cainjector + chart: cainjector-v0.8.0 + release: cert-manager + heritage: Tiller +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["configmaps", "events"] + verbs: ["*"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["*"] + - apiGroups: ["apiregistration.k8s.io"] + resources: ["apiservices"] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: cert-manager-cainjector + labels: + app: cainjector + chart: cainjector-v0.8.0 + release: cert-manager + heritage: Tiller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cert-manager-cainjector +subjects: + - name: cert-manager-cainjector + namespace: "cert-manager" + kind: ServiceAccount +--- +# Source: cert-manager/templates/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: cert-manager + labels: + app: cert-manager + chart: cert-manager-v0.8.0 + release: cert-manager + heritage: Tiller +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "certificates/finalizers", "issuers", "clusterissuers", "orders", "orders/finalizers", "challenges", "challenges/finalizers"] + verbs: ["*"] + - apiGroups: [""] + resources: ["configmaps", "secrets", "events", "services","pods"] + verbs: ["*"] + - apiGroups: ["extensions"] + resources: ["ingresses", "ingresses/finalizers"] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: cert-manager + labels: + app: cert-manager + chart: cert-manager-v0.8.0 + release: cert-manager + heritage: Tiller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cert-manager +subjects: + - name: cert-manager + namespace: "cert-manager" + kind: ServiceAccount +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cert-manager-view + labels: + app: cert-manager + chart: cert-manager-v0.8.0 + release: cert-manager + heritage: Tiller + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "issuers"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cert-manager-edit + labels: + app: cert-manager + chart: cert-manager-v0.8.0 + release: cert-manager + heritage: Tiller + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "issuers"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] + +--- +# Source: cert-manager/charts/webhook/templates/rbac.yaml +### Webhook ### +--- +# apiserver gets the auth-delegator role to delegate auth decisions to +# the core apiserver +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: cert-manager-webhook:auth-delegator + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- apiGroup: "" + kind: ServiceAccount + name: cert-manager-webhook + namespace: cert-manager + +--- + +# apiserver gets the ability to read authentication. This allows it to +# read the specific configmap that has the requestheader-* entries to +# api agg +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: cert-manager-webhook:webhook-authentication-reader + namespace: kube-system + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- apiGroup: "" + kind: ServiceAccount + name: cert-manager-webhook + namespace: cert-manager + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cert-manager-webhook:webhook-requester + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +rules: +- apiGroups: + - admission.certmanager.k8s.io + resources: + - certificates + - issuers + - clusterissuers + verbs: + - create + +--- +# Source: cert-manager/charts/webhook/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: cert-manager-webhook + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + type: ClusterIP + ports: + - name: https + port: 443 + targetPort: 6443 + selector: + app: webhook + release: cert-manager + +--- +# Source: cert-manager/charts/cainjector/templates/deployment.yaml +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: cert-manager-cainjector + namespace: "cert-manager" + labels: + app: cainjector + chart: cainjector-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + replicas: 1 + selector: + matchLabels: + app: cainjector + release: cert-manager + template: + metadata: + labels: + app: cainjector + release: cert-manager + annotations: + spec: + serviceAccountName: cert-manager-cainjector + containers: + - name: cainjector + image: "quay.io/jetstack/cert-manager-cainjector:v0.8.0" + imagePullPolicy: IfNotPresent + args: + - --v=2 + - --leader-election-namespace=$(POD_NAMESPACE) + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + {} + + +--- +# Source: cert-manager/charts/webhook/templates/deployment.yaml +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: cert-manager-webhook + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + replicas: 1 + selector: + matchLabels: + app: webhook + release: cert-manager + template: + metadata: + labels: + app: webhook + release: cert-manager + annotations: + spec: + serviceAccountName: cert-manager-webhook + containers: + - name: webhook + image: "quay.io/jetstack/cert-manager-webhook:v0.8.0" + imagePullPolicy: IfNotPresent + args: + - --v=2 + - --secure-port=6443 + - --tls-cert-file=/certs/tls.crt + - --tls-private-key-file=/certs/tls.key + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + {} + + volumeMounts: + - name: certs + mountPath: /certs + volumes: + - name: certs + secret: + secretName: cert-manager-webhook-webhook-tls + +--- +# Source: cert-manager/templates/deployment.yaml +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: cert-manager + namespace: "cert-manager" + labels: + app: cert-manager + chart: cert-manager-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + replicas: 1 + selector: + matchLabels: + app: cert-manager + release: cert-manager + template: + metadata: + labels: + app: cert-manager + release: cert-manager + annotations: + prometheus.io/path: "/metrics" + prometheus.io/scrape: 'true' + prometheus.io/port: '9402' + spec: + serviceAccountName: cert-manager + containers: + - name: cert-manager + image: "quay.io/jetstack/cert-manager-controller:v0.8.0" + imagePullPolicy: IfNotPresent + args: + - --v=2 + - --cluster-resource-namespace=$(POD_NAMESPACE) + - --leader-election-namespace=$(POD_NAMESPACE) + ports: + - containerPort: 9402 + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + requests: + cpu: 10m + memory: 32Mi + + +--- +# Source: cert-manager/charts/webhook/templates/apiservice.yaml +apiVersion: apiregistration.k8s.io/v1beta1 +kind: APIService +metadata: + name: v1beta1.admission.certmanager.k8s.io + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller + annotations: + certmanager.k8s.io/inject-ca-from: "cert-manager/cert-manager-webhook-webhook-tls" +spec: + group: admission.certmanager.k8s.io + groupPriorityMinimum: 1000 + versionPriority: 15 + service: + name: cert-manager-webhook + namespace: "cert-manager" + version: v1beta1 + +--- +# Source: cert-manager/charts/webhook/templates/pki.yaml +--- +# Create a selfsigned Issuer, in order to create a root CA certificate for +# signing webhook serving certificates +apiVersion: certmanager.k8s.io/v1alpha1 +kind: Issuer +metadata: + name: cert-manager-webhook-selfsign + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + selfSigned: {} + +--- + +# Generate a CA Certificate used to sign certificates for the webhook +apiVersion: certmanager.k8s.io/v1alpha1 +kind: Certificate +metadata: + name: cert-manager-webhook-ca + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + secretName: cert-manager-webhook-ca + duration: 43800h # 5y + issuerRef: + name: cert-manager-webhook-selfsign + commonName: "ca.webhook.cert-manager" + isCA: true + +--- + +# Create an Issuer that uses the above generated CA certificate to issue certs +apiVersion: certmanager.k8s.io/v1alpha1 +kind: Issuer +metadata: + name: cert-manager-webhook-ca + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + ca: + secretName: cert-manager-webhook-ca + +--- + +# Finally, generate a serving certificate for the webhook to use +apiVersion: certmanager.k8s.io/v1alpha1 +kind: Certificate +metadata: + name: cert-manager-webhook-webhook-tls + namespace: "cert-manager" + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller +spec: + secretName: cert-manager-webhook-webhook-tls + duration: 8760h # 1y + issuerRef: + name: cert-manager-webhook-ca + dnsNames: + - cert-manager-webhook + - cert-manager-webhook.cert-manager + - cert-manager-webhook.cert-manager.svc + +--- +# Source: cert-manager/charts/webhook/templates/validating-webhook.yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + name: cert-manager-webhook + labels: + app: webhook + chart: webhook-v0.8.0 + release: cert-manager + heritage: Tiller + annotations: + certmanager.k8s.io/inject-apiserver-ca: "true" +webhooks: + - name: certificates.admission.certmanager.k8s.io + namespaceSelector: + matchExpressions: + - key: "certmanager.k8s.io/disable-validation" + operator: "NotIn" + values: + - "true" + - key: "name" + operator: "NotIn" + values: + - cert-manager + rules: + - apiGroups: + - "certmanager.k8s.io" + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - certificates + failurePolicy: Fail + clientConfig: + service: + name: kubernetes + namespace: default + path: /apis/admission.certmanager.k8s.io/v1beta1/certificates + - name: issuers.admission.certmanager.k8s.io + namespaceSelector: + matchExpressions: + - key: "certmanager.k8s.io/disable-validation" + operator: "NotIn" + values: + - "true" + - key: "name" + operator: "NotIn" + values: + - cert-manager + rules: + - apiGroups: + - "certmanager.k8s.io" + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - issuers + failurePolicy: Fail + clientConfig: + service: + name: kubernetes + namespace: default + path: /apis/admission.certmanager.k8s.io/v1beta1/issuers + - name: clusterissuers.admission.certmanager.k8s.io + namespaceSelector: + matchExpressions: + - key: "certmanager.k8s.io/disable-validation" + operator: "NotIn" + values: + - "true" + - key: "name" + operator: "NotIn" + values: + - cert-manager + rules: + - apiGroups: + - "certmanager.k8s.io" + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - clusterissuers + failurePolicy: Fail + clientConfig: + service: + name: kubernetes + namespace: default + path: /apis/admission.certmanager.k8s.io/v1beta1/clusterissuers + diff --git a/kubernetes/gitea-ingress.yaml b/kubernetes/gitea-ingress.yaml new file mode 100644 index 0000000..b05277f --- /dev/null +++ b/kubernetes/gitea-ingress.yaml @@ -0,0 +1,276 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ingress-controller + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: ingress-controller +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "extensions" + resources: + - ingresses/status + verbs: + - update +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: ingress-controller + namespace: default +rules: + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - apiGroups: + - "" + resources: + - endpoints + verbs: + - get + - create + - update +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: ingress-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ingress-controller +subjects: + - kind: ServiceAccount + name: ingress-controller + namespace: default + - apiGroup: rbac.authorization.k8s.io + kind: User + name: ingress-controller +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: ingress-controller + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ingress-controller +subjects: + - kind: ServiceAccount + name: ingress-controller + namespace: default + - apiGroup: rbac.authorization.k8s.io + kind: User + name: ingress-controller +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + run: ingress-default-backend + name: ingress-default-backend + namespace: default +spec: + selector: + matchLabels: + run: ingress-default-backend + template: + metadata: + labels: + run: ingress-default-backend + spec: + containers: + - name: ingress-default-backend + image: gcr.io/google_containers/defaultbackend:1.0 + ports: + - containerPort: 8080 + resources: + limits: + cpu: 10m + memory: 20Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: ingress-default-backend + namespace: default +spec: + ports: + - port: 8080 + selector: + run: ingress-default-backend +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: haproxy-ingress + namespace: default +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: haproxy-ingress-tcp + namespace: default +data: + "22": "default/gitea-server:22" +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + labels: + run: haproxy-ingress + name: haproxy-ingress + namespace: default +spec: + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + run: haproxy-ingress + template: + metadata: + labels: + run: haproxy-ingress + spec: + hostNetwork: true + nodeSelector: + role: ingress-controller + serviceAccountName: ingress-controller + containers: + - name: haproxy-ingress + image: quay.io/jcmoraisjr/haproxy-ingress + args: + - --default-backend-service=$(POD_NAMESPACE)/ingress-default-backend + - --configmap=$(POD_NAMESPACE)/haproxy-ingress + - --tcp-services-configmap=$(POD_NAMESPACE)/haproxy-ingress-tcp + - --sort-backends + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + - name: stat + containerPort: 1936 + livenessProbe: + httpGet: + path: /healthz + port: 10253 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + value: default +--- +apiVersion: v1 +kind: Service +metadata: + name: gitea-server-nodeport + namespace: default + labels: + app: gitea + name: gitea-server + annotations: + # add an annotation indicating the issuer to use. + # TODO: Switch to production when we're ready + certmanager.k8s.io/cluster-issuer: letsencrypt-staging +spec: + ports: + - name: http + port: 3000 + targetPort: 3000 + - name: ssh + port: 22 + targetPort: 22 + protocol: TCP + type: NodePort + selector: + name: gitea-server +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: gitea-ingress + namespace: default + labels: + name: gitea-server + app: gitea + annotations: + kubernetes.io/ingress.class: "haproxy" +spec: + tls: + - hosts: + - gitea.kosmos.org + secretName: gitea-kosmos-org-cert + rules: + - host: gitea.kosmos.org + http: + paths: + - path: / + backend: + serviceName: gitea-server-nodeport + servicePort: 3000 diff --git a/kubernetes/gitea-server.yaml b/kubernetes/gitea-server.yaml index 95eb759..3822abb 100644 --- a/kubernetes/gitea-server.yaml +++ b/kubernetes/gitea-server.yaml @@ -32,8 +32,21 @@ spec: image: gitea/gitea:1.8.1 ports: - containerPort: 3000 - - containerPort: 3001 - containerPort: 22 + livenessProbe: + httpGet: + path: / + port: 3000 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: 3000 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 5 volumeMounts: - mountPath: /data name: gitea-server-data @@ -93,9 +106,6 @@ spec: targetPort: 22 - name: "http" port: 80 - targetPort: 3001 - - name: "https" - port: 443 targetPort: 3000 selector: name: gitea-server diff --git a/kubernetes/letsencrypt-production.yaml b/kubernetes/letsencrypt-production.yaml new file mode 100644 index 0000000..13df87b --- /dev/null +++ b/kubernetes/letsencrypt-production.yaml @@ -0,0 +1,19 @@ +apiVersion: certmanager.k8s.io/v1alpha1 +kind: ClusterIssuer +metadata: + name: letsencrypt-production +spec: + acme: + # You must replace this email address with your own. + # Let's Encrypt will use this to contact you about expiring + # certificates, and issues related to your account. + email: ops@kosmos.org + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + # Secret resource used to store the account's private key. + name: letsencrypt-production-account-key + # Add a single challenge solver, HTTP01 using nginx + solvers: + - http01: + ingress: + class: nginx diff --git a/kubernetes/letsencrypt-staging.yaml b/kubernetes/letsencrypt-staging.yaml new file mode 100644 index 0000000..cc2094e --- /dev/null +++ b/kubernetes/letsencrypt-staging.yaml @@ -0,0 +1,19 @@ +apiVersion: certmanager.k8s.io/v1alpha1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + # You must replace this email address with your own. + # Let's Encrypt will use this to contact you about expiring + # certificates, and issues related to your account. + email: ops@kosmos.org + server: https://acme-staging-v02.api.letsencrypt.org/directory + privateKeySecretRef: + # Secret resource used to store the account's private key. + name: letsencrypt-staging-account-key + # Add a single challenge solver, HTTP01 using nginx + solvers: + - http01: + ingress: + class: nginx -- 2.25.1 From ed48c92e4f10476a2f1b3ab396014c8d926b264a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Thu, 4 Jul 2019 14:44:20 +0200 Subject: [PATCH 2/5] Update cert-manager to 0.8.1 --- kubernetes/cert-manager.yaml | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/kubernetes/cert-manager.yaml b/kubernetes/cert-manager.yaml index 69638aa..0c1ebb5 100644 --- a/kubernetes/cert-manager.yaml +++ b/kubernetes/cert-manager.yaml @@ -1,5 +1,5 @@ # cert-manager docs are at https://cert-manager.readthedocs.io/en/latest/getting-started/install/kubernetes.html -# This file was copied from https://github.com/jetstack/cert-manager/releases/download/v0.8.0/cert-manager.yaml +# This file was copied from https://github.com/jetstack/cert-manager/releases/download/v0.8.1/cert-manager.yaml # It must be applied with `kubectl apply -f cert-manager.yaml --validate=false` # on Kubernetes < 1.13 apiVersion: apiextensions.k8s.io/v1beta1 @@ -1208,7 +1208,7 @@ metadata: namespace: "cert-manager" labels: app: cainjector - chart: cainjector-v0.8.0 + chart: cainjector-v0.8.1 release: cert-manager heritage: Tiller @@ -1221,7 +1221,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller @@ -1234,7 +1234,7 @@ metadata: namespace: "cert-manager" labels: app: cert-manager - chart: cert-manager-v0.8.0 + chart: cert-manager-v0.8.1 release: cert-manager heritage: Tiller @@ -1246,7 +1246,7 @@ metadata: name: cert-manager-cainjector labels: app: cainjector - chart: cainjector-v0.8.0 + chart: cainjector-v0.8.1 release: cert-manager heritage: Tiller rules: @@ -1272,7 +1272,7 @@ metadata: name: cert-manager-cainjector labels: app: cainjector - chart: cainjector-v0.8.0 + chart: cainjector-v0.8.1 release: cert-manager heritage: Tiller roleRef: @@ -1291,7 +1291,7 @@ metadata: name: cert-manager labels: app: cert-manager - chart: cert-manager-v0.8.0 + chart: cert-manager-v0.8.1 release: cert-manager heritage: Tiller rules: @@ -1311,7 +1311,7 @@ metadata: name: cert-manager labels: app: cert-manager - chart: cert-manager-v0.8.0 + chart: cert-manager-v0.8.1 release: cert-manager heritage: Tiller roleRef: @@ -1329,7 +1329,7 @@ metadata: name: cert-manager-view labels: app: cert-manager - chart: cert-manager-v0.8.0 + chart: cert-manager-v0.8.1 release: cert-manager heritage: Tiller rbac.authorization.k8s.io/aggregate-to-view: "true" @@ -1346,7 +1346,7 @@ metadata: name: cert-manager-edit labels: app: cert-manager - chart: cert-manager-v0.8.0 + chart: cert-manager-v0.8.1 release: cert-manager heritage: Tiller rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -1368,7 +1368,7 @@ metadata: name: cert-manager-webhook:auth-delegator labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller roleRef: @@ -1393,7 +1393,7 @@ metadata: namespace: kube-system labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller roleRef: @@ -1414,7 +1414,7 @@ metadata: name: cert-manager-webhook:webhook-requester labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller rules: @@ -1436,7 +1436,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1458,7 +1458,7 @@ metadata: namespace: "cert-manager" labels: app: cainjector - chart: cainjector-v0.8.0 + chart: cainjector-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1477,7 +1477,7 @@ spec: serviceAccountName: cert-manager-cainjector containers: - name: cainjector - image: "quay.io/jetstack/cert-manager-cainjector:v0.8.0" + image: "quay.io/jetstack/cert-manager-cainjector:v0.8.1" imagePullPolicy: IfNotPresent args: - --v=2 @@ -1500,7 +1500,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1519,7 +1519,7 @@ spec: serviceAccountName: cert-manager-webhook containers: - name: webhook - image: "quay.io/jetstack/cert-manager-webhook:v0.8.0" + image: "quay.io/jetstack/cert-manager-webhook:v0.8.1" imagePullPolicy: IfNotPresent args: - --v=2 @@ -1551,7 +1551,7 @@ metadata: namespace: "cert-manager" labels: app: cert-manager - chart: cert-manager-v0.8.0 + chart: cert-manager-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1573,7 +1573,7 @@ spec: serviceAccountName: cert-manager containers: - name: cert-manager - image: "quay.io/jetstack/cert-manager-controller:v0.8.0" + image: "quay.io/jetstack/cert-manager-controller:v0.8.1" imagePullPolicy: IfNotPresent args: - --v=2 @@ -1600,7 +1600,7 @@ metadata: name: v1beta1.admission.certmanager.k8s.io labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller annotations: @@ -1626,7 +1626,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1642,7 +1642,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1663,7 +1663,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1680,7 +1680,7 @@ metadata: namespace: "cert-manager" labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller spec: @@ -1701,7 +1701,7 @@ metadata: name: cert-manager-webhook labels: app: webhook - chart: webhook-v0.8.0 + chart: webhook-v0.8.1 release: cert-manager heritage: Tiller annotations: -- 2.25.1 From 91dab0f1213eaf58bb333215b171b68cf3621b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Thu, 4 Jul 2019 14:44:49 +0200 Subject: [PATCH 3/5] Explicitly set the ingress name to gitea-ingress The old config was generating a separate nginx ingress instead of attaching the HTTP challenge URL to our existing ingress (gitea-ingress) --- kubernetes/letsencrypt-production.yaml | 5 +++-- kubernetes/letsencrypt-staging.yaml | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/kubernetes/letsencrypt-production.yaml b/kubernetes/letsencrypt-production.yaml index 13df87b..31fb724 100644 --- a/kubernetes/letsencrypt-production.yaml +++ b/kubernetes/letsencrypt-production.yaml @@ -12,8 +12,9 @@ spec: privateKeySecretRef: # Secret resource used to store the account's private key. name: letsencrypt-production-account-key - # Add a single challenge solver, HTTP01 using nginx + # Add a single challenge solver, HTTP01 using the gitea-ingress + # https://docs.cert-manager.io/en/latest/reference/api-docs/index.html#acmechallengesolverhttp01ingress-v1alpha1 solvers: - http01: ingress: - class: nginx + name: gitea-ingress diff --git a/kubernetes/letsencrypt-staging.yaml b/kubernetes/letsencrypt-staging.yaml index cc2094e..6e7acc2 100644 --- a/kubernetes/letsencrypt-staging.yaml +++ b/kubernetes/letsencrypt-staging.yaml @@ -4,7 +4,6 @@ metadata: name: letsencrypt-staging spec: acme: - # You must replace this email address with your own. # Let's Encrypt will use this to contact you about expiring # certificates, and issues related to your account. email: ops@kosmos.org @@ -12,8 +11,9 @@ spec: privateKeySecretRef: # Secret resource used to store the account's private key. name: letsencrypt-staging-account-key - # Add a single challenge solver, HTTP01 using nginx + # Add a single challenge solver, HTTP01 using the gitea-ingress + # https://docs.cert-manager.io/en/latest/reference/api-docs/index.html#acmechallengesolverhttp01ingress-v1alpha1 solvers: - http01: ingress: - class: nginx + name: gitea-ingress -- 2.25.1 From 3cdc07cdf369512159c70c18547844e52371cf79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Thu, 4 Jul 2019 17:34:19 +0200 Subject: [PATCH 4/5] Add initial Ingress documentation --- doc/ingress.md | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 doc/ingress.md diff --git a/doc/ingress.md b/doc/ingress.md new file mode 100644 index 0000000..490c0ef --- /dev/null +++ b/doc/ingress.md @@ -0,0 +1,180 @@ +# HTTP(S) load balancing with Ingress + +## Resources + +Features of GKE Ingress from the Google Cloud docs: +https://cloud.google.com/kubernetes-engine/docs/concepts/ingress + +It does hostname-aware HTTP(S) load balancing, and is billed like a regular +Load Balancer (https://cloud.google.com/compute/pricing#lb). The advantages are +that we can use one set of firewall rules (ports 80 and 443) for multiple +services, and easy Let's Encrypt certificates for services with no built-in +support for it + +This 3 part article was a good resource: + +https://medium.com/google-cloud/global-kubernetes-in-3-steps-on-gcp-8a3585ec8547 +https://medium.com/google-cloud/global-ingress-in-practice-on-google-container-engine-part-1-discussion-ccc1e5b27bd0 +https://medium.com/google-cloud/global-ingress-in-practice-on-google-container-engine-part-2-demo-cf587765702 + +I couldn't find information about setting +`ingress.kubernetes.io/rewrite-target` to `/` anywhere else, without it only +`/` worked on an host, all other URLs would go to the default backend and +return a 404. + +cert-manager, for automated (among others) Let's Encrypt certificates: +https://docs.cert-manager.io/en/release-0.8/ + +## Create a global IP + +Ephemeral IPs are only regional, and you lose them if you have to recreate the +Ingress + + gcloud compute addresses create ingress-ip --global + +## Create the ingress + +A ClusterIP will not work, because it is allocating random ports. Explicitly +create a NodePort to expose your service. On GKE, health checks are configured +automatically + + cat < test-server-nodeport.yaml + apiVersion: v1 + kind: Service + metadata: + name: test-server-nodeport + spec: + ports: + - name: http + port: 80 + targetPort: 3000 + type: NodePort + selector: + name: test-server + EOF + kubectl apply -f test-server-nodeport.yaml + +Create the ingress resource + + cat < ingress-main.yaml + # A GCE Ingress that uses cert-manager to manage Let's Encrypt certificates + apiVersion: extensions/v1beta1 + kind: Ingress + metadata: + name: gitea-ingress + annotations: + # Required, otherwise only the / path works + # https://medium.com/google-cloud/global-ingress-in-practice-on-google-container-engine-part-1-discussion-ccc1e5b27bd0 + ingress.kubernetes.io/rewrite-target: / + certmanager.k8s.io/cluster-issuer: "letsencrypt-production" + certmanager.k8s.io/acme-challenge-type: http01 + # Created using the following command + # gcloud compute addresses create ingress-ip --global + kubernetes.io/ingress.global-static-ip-name: "ingress-ip" + spec: + tls: + - hosts: + - test.kosmos.org + secretName: test-kosmos-org-cert + - test2.kosmos.org + secretName: test2-kosmos-org-cert + rules: + - host: test.kosmos.org + http: + paths: + - backend: + serviceName: test-server-nodeport + servicePort: 80 + - host: test2.kosmos.org + http: + paths: + - backend: + serviceName: test-server-nodeport + servicePort: 80 + EOF + kubectl apply -f ingress-main.yaml + + +## cert-manager + +### Create the cert-manager resources + +cert-manager provides a Let's Encrypt certificate issuer, and lets you mount it +in an Ingress resource, making it possible to use HTTP ACME challenges + +Get the reserved IP you created in the first step: + + $ gcloud compute addresses list --global + NAME ADDRESS/RANGE TYPE PURPOSE NETWORK REGION SUBNET STATUS + ingress-ip 35.244.164.133 EXTERNAL IN_USE + +Set the DNS record for the domain you want a Let's Encrypt cert for to this IP. + +Now it's time to create the cert-manager + +https://docs.cert-manager.io/en/release-0.8/getting-started/install/kubernetes.html + + kubectl create namespace cert-manager + + kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v0.8.1/cert-manager.yaml --validate=false + +I had to run the apply command twice for it to create all the resources. On the +first run I got these errors. Running it a second time successfully created all +the resources + + unable to recognize "cert-manager.yaml": no matches for kind "Issuer" in version "certmanager.k8s.io/v1alpha1" + unable to recognize "cert-manager.yaml": no matches for kind "Certificate" in version "certmanager.k8s.io/v1alpha1" + unable to recognize "cert-manager.yaml": no matches for kind "Issuer" in version "certmanager.k8s.io/v1alpha1" + unable to recognize "cert-manager.yaml": no matches for kind "Certificate" in version "certmanager.k8s.io/v1alpha1" + +We name the ingress explicitely so it only runs on one. Having only one IP to +set on the DNS records makes the HTTP validation easier. Using the class would +attach the validation endpoint to all Ingresses of that class +(https://docs.cert-manager.io/en/latest/reference/api-docs/index.html#acmechallengesolverhttp01ingress-v1alpha1) + + cat < letsencrypt-staging.yaml + apiVersion: certmanager.k8s.io/v1alpha1 + kind: ClusterIssuer + metadata: + name: letsencrypt-staging + spec: + acme: + # Let's Encrypt will use this to contact you about expiring + # certificates, and issues related to your account. + email: ops@kosmos.org + server: https://acme-staging-v02.api.letsencrypt.org/directory + privateKeySecretRef: + # Secret resource used to store the account's private key. + name: letsencrypt-staging-account-key + solvers: + - http01: + ingress: + name: gitea-ingress + EOF + + cat < letsencrypt-production.yaml + apiVersion: certmanager.k8s.io/v1alpha1 + kind: ClusterIssuer + metadata: + name: letsencrypt-production + spec: + acme: + # Let's Encrypt will use this to contact you about expiring + # certificates, and issues related to your account. + email: ops@kosmos.org + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + # Secret resource used to store the account's private key. + name: letsencrypt-production-account-key + solvers: + - http01: + ingress: + name: gitea-ingress + + +## Add another service + +To add another service behind the Ingress, you set the DNS entry for its domain +to the Ingress IP, deploy your service, create a NodePort to expose it, and +finally add its host to the Ingress config (both tls and rules, see example +above) -- 2.25.1 From 67d87d7d5b7a53b564dbea0c3dc002d92750087b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Kar=C3=A9kinian?= Date: Fri, 5 Jul 2019 11:13:22 +0200 Subject: [PATCH 5/5] Use the correct name for the ingress --- doc/ingress.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ingress.md b/doc/ingress.md index 490c0ef..9ce7600 100644 --- a/doc/ingress.md +++ b/doc/ingress.md @@ -61,7 +61,7 @@ Create the ingress resource apiVersion: extensions/v1beta1 kind: Ingress metadata: - name: gitea-ingress + name: ingress-main annotations: # Required, otherwise only the / path works # https://medium.com/google-cloud/global-ingress-in-practice-on-google-container-engine-part-1-discussion-ccc1e5b27bd0 @@ -149,7 +149,7 @@ attach the validation endpoint to all Ingresses of that class solvers: - http01: ingress: - name: gitea-ingress + name: ingress-main EOF cat < letsencrypt-production.yaml @@ -169,7 +169,7 @@ attach the validation endpoint to all Ingresses of that class solvers: - http01: ingress: - name: gitea-ingress + name: ingress-main ## Add another service -- 2.25.1