Skip to content

WIP: Introduce mutating webhook for sidecar injection.#1423

Closed
Bedotech wants to merge 2 commits intolinkerd:masterfrom
criptalia:add-mutating-webhook-for-sidecar-injection
Closed

WIP: Introduce mutating webhook for sidecar injection.#1423
Bedotech wants to merge 2 commits intolinkerd:masterfrom
criptalia:add-mutating-webhook-for-sidecar-injection

Conversation

@Bedotech
Copy link

@Bedotech Bedotech commented Aug 8, 2018

For manage deployment with linkerd2 with other tools like helm is really
important to make the pod injection at the lower level we can.

#561 Using MutatingWebhook (new k8s 1.9) we can modify a pod before the pod
is created.

So far i have created:

  • new container called 'sidecar-injection'
  • update install profile for add 'sidecar-injection'
  • create for now fake webhook for test integration

This PR is really WIP, before we have to solve:

  • Ho we issue certificate for webhook in k8s
  • Link the webhook inject handler with existing api for sidecar
    injection.
  • code review.

Signed-off-by: Mattia Rossi [email protected]

@grampelberg grampelberg requested a review from klingerf August 8, 2018 15:16
@grampelberg grampelberg requested review from rmars and removed request for klingerf August 9, 2018 17:52
Copy link

@rmars rmars left a comment

Choose a reason for hiding this comment

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

🎉 thank you for undertaking this, @Bedotech!

This PR is a good starting point for us to start to think about and flesh out some of the design tradeoffs we'll need to make.

I discussed this with the team and the main design considerations we'd like to start thinking about are:

  • how we can integrate this into the install experience such that the user can do minimal work. Can the cert setup be included as part of linkerd install? How much work would it be to get there from here? Is it worth doing it as a follow up, or can we get it integrated now?
    Can we use our existing TLS bootstrapping?

  • can the webhook server be another subcomponent in the cmd/ directory? this way we can build and maintain fewer docker images

We'd also like to run the TLS setup we decide on by @briansmith before it merges.

I also had a couple of starting smaller review points. A lot of the code here is likely to change as we think through this together, but this is a great start!


## Setup

Once you have create the secret you can run `linkerd install`, for automatic
Copy link

Choose a reason for hiding this comment

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

As mentioned above, eventually we'll want to find a way to have this be run from linkerd install (seeing if gating the admisison controller feature behind a flag is possible)

Copy link
Author

Choose a reason for hiding this comment

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

Ok i think this can be done after we can effectively inject

}

func init() {
_ = corev1.AddToScheme(runtimeScheme)
Copy link

Choose a reason for hiding this comment

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

I think we can omit the _ = if we're just throwing out all these results anyway

"os/signal"
"syscall"

"github.com/golang/glog"
Copy link

Choose a reason for hiding this comment

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

note that we use sirupsen/logrus for logging instead of glog- we'll need to move these over.


func updateAnnotation(target map[string]string, added map[string]string) (patch []patchOperation) {
for key, value := range added {
if target == nil || target[key] == "" {
Copy link

Choose a reason for hiding this comment

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

should this second || target[key] be here? if target[key] doesn't exist, do we want to re-initialize the entire annotation map?

} else {
patch = append(patch, patchOperation{
Op: "replace",
Path: "/metadata/annotations/" + key,
Copy link

Choose a reason for hiding this comment

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

Do we need to escape the key here?

// the Path of the JSON patch is a JSON pointer value
// so we need to escape any "/"s in the key we add to the annotation
// https://tools.ietf.org/html/rfc6901
func escapeJSONPointer(s string) string {
	esc := strings.Replace(s, "~", "~0", -1)
	esc = strings.Replace(esc, "/", "~1", -1)
	return esc
}

@@ -0,0 +1,64 @@
+++
Copy link

Choose a reason for hiding this comment

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

😻 thank you for adding documentation!


// get command line parameters
flag.IntVar(&parameters.port, "port", 443, "Webhook server port.")
flag.StringVar(&parameters.certFile, "tlsCertFile", "/etc/webhook/certs/cert.pem", "File containing the x509 Certificate for HTTPS.")
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should follow the convention used by the other controllers' flags i.e. tls-cert-file, instead of tlsCertFile.


var body []byte
if r.Body != nil {
if data, err := ioutil.ReadAll(r.Body); err == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should handle the case of err !=nil. Otherwise, the empty body error below will be returned to the user which can be misleading.

}

func addContainer(target, added []corev1.Container, basePath string) (patch []patchOperation) {
first := len(target) == 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible for target's length to be 0?

admissionResponse = whsvr.mutate(&ar)
}

admissionReview := v1beta1.AdmissionReview{}
Copy link
Contributor

@ihcsim ihcsim Aug 20, 2018

Choose a reason for hiding this comment

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

Might not need this and re-use ar from line 279. The AdmissionReview type has both a Request and a Response fields.

Mattia Rossi added 2 commits August 20, 2018 19:01
For manage deployment with linkerd2 with other tools like helm is really
important to make the pod injection at the lower level we can.

Using MutatingWebhook (new k8s 1.9) we can modify a pod before the pod
is created.

So far i have created:
* new container called 'sidecar-injection'
* update install profile for add 'sidecar-injection'
* create for now fake webhook for test integration

This PR is really WIP, before we have to solve:
* Ho we issue certificate for webhook in k8s
* Link the webhook inject handler with existing api for sidecar
injection.
* code review.

Signed-off-by: Mattia Rossi <[email protected]>
Trye to solve the SSL problem with .sh script that sign a certificate
using kubectl.
@Bedotech Bedotech force-pushed the add-mutating-webhook-for-sidecar-injection branch from a1ac10c to a720829 Compare August 20, 2018 17:01
https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster for
detailed explantion and additional instructions.

The server key/cert k8s CA cert are stored in a k8s secret.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this will work as a long-term solution:

  1. The private key for the certificate shouldn't ever be outside the cluster, so this script should be run from within the controller, not by the user.

  2. The CertificateSigningRequest API isn't always enabled and even when enabled isn't always configured in a usable state. For example and in particular, I don't think minikube enables this in its default configuration.

  3. AFAICT, using the CertificateSigningRequest API isn't necessary because the webhook configuration YAML lets you specify the CA to be trusted for the webhook.

The way I was thinking to do this is as follows:

  1. conduit install installs the webhook along with the rest of the control plane but it won't work yet because the object properties that indicates the webhook's CA won't be written yet.
  2. When the CA starts up, (and in the future, whenever the root CA certificates change) the CA replaces the webhooks configuration with one that has its own certificate as the trusted CA certificate. This requires the CA to have edit properties for the webhook configuration object.

After step 2 the webhook should work.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, this is really the first implementation, if you look at Istio the setup and creation of the certificate is made at the setup time using k8s api.

The point 1 or 2 are prerequisite.

Only one point, i have made all test against clean minikube environment and all is working , so i think the CertificateSigningRequest it's enabled by default.

Copy link
Contributor

Choose a reason for hiding this comment

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

... creation of the certificate is made at the setup time using k8s api.

Not 100% sure, from what I see in the citadel code, they may no longer be relying on the k8s api to generate and sign CSR. Can you confirm?

References:

  1. security/cmd/istio_ca/main.go#L427-L454)
  2. security/pkg/pki/ca/ca.go#L174-L194
  3. security/pkg/pki/util/generate_cert.go#L107-L114

@cppforlife
Copy link

cppforlife commented Sep 21, 2018

@klingerf
Copy link
Contributor

@Bedotech Thanks for your hard work on this. Auto injection support was added in #1714, so I'm going to close out this PR. Thanks again for doing so much initial investigation.

@klingerf klingerf closed this Oct 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants