Skip to content

Commit

Permalink
Revert "Remove fastcgi feature" (#10081)
Browse files Browse the repository at this point in the history
* Revert "Remove fastcgi feature (#9864)"

This reverts commit 90ed0cc.

* revert fastcgi* annotations warning

Signed-off-by: Jintao Zhang <[email protected]>

---------

Signed-off-by: Jintao Zhang <[email protected]>
  • Loading branch information
tao12345666333 authored Jun 13, 2023
1 parent f1e3f2f commit cccba35
Show file tree
Hide file tree
Showing 25 changed files with 975 additions and 159 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ jobs:
- 'images/custom-error-pages/**'
cfssl:
- 'images/cfssl/**'
fastcgi-helloserver:
- 'images/fastcgi-helloserver/**'
echo:
- 'images/echo/**'
go-grpc-greeter-server:
Expand All @@ -410,6 +412,10 @@ jobs:
if: ${{ steps.filter-images.outputs.cfssl == 'true' }}
run: |
cd images/cfssl && make build
- name: fastcgi-helloserver
if: ${{ steps.filter-images.outputs.fastcgi-helloserver == 'true' }}
run: |
cd images/fastcgi-helloserver && make build
- name: echo image build
if: ${{ steps.filter-images.outputs.echo == 'true' }}
run: |
Expand Down
2 changes: 2 additions & 0 deletions MANUAL_RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@

- [cfssl](https://github.com/kubernetes/ingress-nginx/tree/main/images/cfssl)

- [fastcgi-helloserver](https://github.com/kubernetes/ingress-nginx/tree/main/images/fastcgi-helloserver)

- [httpbin](https://github.com/kubernetes/ingress-nginx/tree/main/images/httpbin)

- [kube-webhook-certgen](https://github.com/kubernetes/ingress-nginx/tree/main/images/kube-webhook-certgen)
Expand Down
131 changes: 12 additions & 119 deletions docs/e2e-tests.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/kubectl-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ kubectl ingress-nginx conf -n ingress-nginx --host testaddr.local

```console
$ kubectl ingress-nginx exec -i -n ingress-nginx -- ls /etc/nginx
fastcgi_params
geoip
lua
mime.types
Expand Down
118 changes: 113 additions & 5 deletions docs/user-guide/fcgi-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,118 @@

# Exposing FastCGI Servers

**This feature has been removed from Ingress NGINX**
> **FastCGI** is a [binary protocol](https://en.wikipedia.org/wiki/Binary_protocol "Binary protocol") for interfacing interactive programs with a [web server](https://en.wikipedia.org/wiki/Web_server "Web server"). [...] (It's) aim is to reduce the overhead related to interfacing between web server and CGI programs, allowing a server to handle more web page requests per unit of time.
>
> &mdash; Wikipedia
People willing to use fastcgi servers, should create an NGINX + FastCGI service and expose
this service via Ingress NGINX.
The _ingress-nginx_ ingress controller can be used to directly expose [FastCGI](https://en.wikipedia.org/wiki/FastCGI) servers. Enabling FastCGI in your Ingress only requires setting the _backend-protocol_ annotation to `FCGI`, and with a couple more annotations you can customize the way _ingress-nginx_ handles the communication with your FastCGI _server_.

We recommend using images like `cgr.dev/chainguard/nginx:latest` and expose your fast_cgi application
as another container on this Pod.

## Example Objects to Expose a FastCGI Pod

The _Pod_ example object below exposes port `9000`, which is the conventional FastCGI port.

```yaml
apiVersion: v1
kind: Pod
metadata:
name: example-app
labels:
app: example-app
spec:
containers:
- name: example-app
image: example-app:1.0
ports:
- containerPort: 9000
name: fastcgi
```
The _Service_ object example below matches port `9000` from the _Pod_ object above.

```yaml
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: example-app
ports:
- port: 9000
targetPort: 9000
name: fastcgi
```

And the _Ingress_ and _ConfigMap_ objects below demonstrates the supported _FastCGI_ specific annotations (NGINX actually has 50 FastCGI directives, all of which have not been exposed in the ingress yet), and matches the service `example-service`, and the port named `fastcgi` from above. The _ConfigMap_ **must** be created first for the _Ingress Controller_ to be able to find it when the _Ingress_ object is created, otherwise you will need to restart the _Ingress Controller_ pods.

```yaml
# The ConfigMap MUST be created first for the ingress controller to be able to
# find it when the Ingress object is created.
apiVersion: v1
kind: ConfigMap
metadata:
name: example-cm
data:
SCRIPT_FILENAME: "/example/index.php"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "FCGI"
nginx.ingress.kubernetes.io/fastcgi-index: "index.php"
nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-cm"
name: example-app
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
name: fastcgi
```

## FastCGI Ingress Annotations

To enable FastCGI, the `nginx.ingress.kubernetes.io/backend-protocol` annotation needs to be set to `FCGI`, which overrides the default `HTTP` value.

> `nginx.ingress.kubernetes.io/backend-protocol: "FCGI"`

**This enables the _FastCGI_ mode for all paths defined in the _Ingress_ object**

### The `nginx.ingress.kubernetes.io/fastcgi-index` Annotation

To specify an index file, the `fastcgi-index` annotation value can optionally be set. In the example below, the value is set to `index.php`. This annotation corresponds to [the _NGINX_ `fastcgi_index` directive](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_index).

> `nginx.ingress.kubernetes.io/fastcgi-index: "index.php"`

### The `nginx.ingress.kubernetes.io/fastcgi-params-configmap` Annotation

To specify [_NGINX_ `fastcgi_param` directives](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_param), the `fastcgi-params-configmap` annotation is used, which in turn must lead to a _ConfigMap_ object containing the _NGINX_ `fastcgi_param` directives as key/values.

> `nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-configmap"`

And the _ConfigMap_ object to specify the `SCRIPT_FILENAME` and `HTTP_PROXY` _NGINX's_ `fastcgi_param` directives will look like the following:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: example-configmap
data:
SCRIPT_FILENAME: "/example/index.php"
HTTP_PROXY: ""
```
Using the _namespace/_ prefix is also supported, for example:

> `nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-namespace/example-configmap"`
2 changes: 1 addition & 1 deletion docs/user-guide/nginx-configuration/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
### Backend Protocol

Using `backend-protocol` annotations is possible to indicate how NGINX should communicate with the backend service. (Replaces `secure-backends` in older versions)
Valid Values: HTTP, HTTPS, GRPC, GRPCS, AJP
Valid Values: HTTP, HTTPS, GRPC, GRPCS, AJP and FCGI

By default NGINX uses `HTTP`.

Expand Down
59 changes: 59 additions & 0 deletions images/fastcgi-helloserver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2020 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Docker image for e2e testing.

# set default shell
SHELL=/bin/bash -o pipefail -o errexit

DIR:=$(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
INIT_BUILDX=$(DIR)/../../hack/init-buildx.sh

SHORT_SHA ?=$(shell git rev-parse --short HEAD)
TAG ?=v$(shell date +%Y%m%d)-$(SHORT_SHA)

REGISTRY ?= local

IMAGE = $(REGISTRY)/e2e-test-fastcgi-helloserver

# required to enable buildx
export DOCKER_CLI_EXPERIMENTAL=enabled

# build with buildx
PLATFORMS?=linux/amd64,linux/arm,linux/arm64
OUTPUT=
PROGRESS=plain

build: ensure-buildx
docker buildx build \
--platform=${PLATFORMS} $(OUTPUT) \
--progress=$(PROGRESS) \
--pull \
-t $(IMAGE):$(TAG) rootfs

# push the cross built image
push: OUTPUT=--push
push: build

# enable buildx
ensure-buildx:
# this is required for cloudbuild
ifeq ("$(wildcard $(INIT_BUILDX))","")
@curl -sSL https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/hack/init-buildx.sh | bash
else
@exec $(INIT_BUILDX)
endif
@echo "done"

.PHONY: build push ensure-buildx
22 changes: 22 additions & 0 deletions images/fastcgi-helloserver/cloudbuild.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
timeout: 1800s
options:
substitution_option: ALLOW_LOOSE
steps:
- name: gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v20211118-2f2d816b90
entrypoint: bash
env:
- DOCKER_CLI_EXPERIMENTAL=enabled
- SHORT_SHA=$SHORT_SHA
- BASE_REF=$_PULL_BASE_REF
- REGISTRY=gcr.io/k8s-staging-ingress-nginx
# default cloudbuild has HOME=/builder/home and docker buildx is in /root/.docker/cli-plugins/docker-buildx
# set the home to /root explicitly to if using docker buildx
- HOME=/root
args:
- -c
- |
gcloud auth configure-docker \
&& cd images/fastcgi-helloserver && make push
substitutions:
_GIT_TAG: "12345"
_PULL_BASE_REF: "master"
32 changes: 32 additions & 0 deletions images/fastcgi-helloserver/rootfs/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright 2017 The Kubernetes Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

FROM golang:1.20.4-alpine3.18 as builder

WORKDIR /go/src/k8s.io/ingress-nginx/images/fastcgi

COPY . .

RUN CGO_ENABLED=0 go build -a -installsuffix cgo \
-ldflags "-s -w" \
-o fastcgi-helloserver main.go

# Use distroless as minimal base image to package the binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot

COPY --from=builder /go/src/k8s.io/ingress-nginx/images/fastcgi/fastcgi-helloserver /
USER nonroot:nonroot

CMD ["/fastcgi-helloserver"]
30 changes: 30 additions & 0 deletions images/fastcgi-helloserver/rootfs/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"fmt"
"net"
"net/http"
"net/http/fcgi"
)

func hello(w http.ResponseWriter, r *http.Request) {
keys, ok := r.URL.Query()["name"]

if !ok || len(keys[0]) < 1 {
fmt.Fprintf(w, "Hello world!")
return
}

key := keys[0]
fmt.Fprintf(w, "Hello "+string(key)+"!")
}

func main() {
http.HandleFunc("/hello", hello)

l, err := net.Listen("tcp", "0.0.0.0:9000")
if err != nil {
panic(err)
}
fcgi.Serve(l, nil)
}
62 changes: 33 additions & 29 deletions internal/ingress/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
"k8s.io/ingress-nginx/internal/ingress/annotations/customhttperrors"
"k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend"
"k8s.io/ingress-nginx/internal/ingress/annotations/fastcgi"
"k8s.io/ingress-nginx/internal/ingress/annotations/globalratelimit"
"k8s.io/ingress-nginx/internal/ingress/annotations/http2pushpreload"
"k8s.io/ingress-nginx/internal/ingress/annotations/ipdenylist"
Expand Down Expand Up @@ -85,35 +86,37 @@ type Ingress struct {
CorsConfig cors.Config
CustomHTTPErrors []int
DefaultBackend *apiv1.Service
Denied *string
ExternalAuth authreq.Config
EnableGlobalAuth bool
HTTP2PushPreload bool
Opentracing opentracing.Config
Opentelemetry opentelemetry.Config
Proxy proxy.Config
ProxySSL proxyssl.Config
RateLimit ratelimit.Config
GlobalRateLimit globalratelimit.Config
Redirect redirect.Config
Rewrite rewrite.Config
Satisfy string
ServerSnippet string
ServiceUpstream bool
SessionAffinity sessionaffinity.Config
SSLPassthrough bool
UsePortInRedirects bool
UpstreamHashBy upstreamhashby.Config
LoadBalancing string
UpstreamVhost string
Whitelist ipwhitelist.SourceRange
Denylist ipdenylist.SourceRange
XForwardedPrefix string
SSLCipher sslcipher.Config
Logs log.Config
ModSecurity modsecurity.Config
Mirror mirror.Config
StreamSnippet string
//TODO: Change this back into an error when https://github.com/imdario/mergo/issues/100 is resolved
FastCGI fastcgi.Config
Denied *string
ExternalAuth authreq.Config
EnableGlobalAuth bool
HTTP2PushPreload bool
Opentracing opentracing.Config
Opentelemetry opentelemetry.Config
Proxy proxy.Config
ProxySSL proxyssl.Config
RateLimit ratelimit.Config
GlobalRateLimit globalratelimit.Config
Redirect redirect.Config
Rewrite rewrite.Config
Satisfy string
ServerSnippet string
ServiceUpstream bool
SessionAffinity sessionaffinity.Config
SSLPassthrough bool
UsePortInRedirects bool
UpstreamHashBy upstreamhashby.Config
LoadBalancing string
UpstreamVhost string
Whitelist ipwhitelist.SourceRange
Denylist ipdenylist.SourceRange
XForwardedPrefix string
SSLCipher sslcipher.Config
Logs log.Config
ModSecurity modsecurity.Config
Mirror mirror.Config
StreamSnippet string
}

// Extractor defines the annotation parsers to be used in the extraction of annotations
Expand All @@ -135,6 +138,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
"CorsConfig": cors.NewParser(cfg),
"CustomHTTPErrors": customhttperrors.NewParser(cfg),
"DefaultBackend": defaultbackend.NewParser(cfg),
"FastCGI": fastcgi.NewParser(cfg),
"ExternalAuth": authreq.NewParser(cfg),
"EnableGlobalAuth": authreqglobal.NewParser(cfg),
"HTTP2PushPreload": http2pushpreload.NewParser(cfg),
Expand Down
Loading

0 comments on commit cccba35

Please sign in to comment.