์ด ํ์ด์ง๋ Apigee์ ์ ์ฉ๋์ง๋ง Apigee Hybrid์๋ ์ ์ฉ๋์ง ์์ต๋๋ค.
Apigee Edge ๋ฌธ์ ๋ณด๊ธฐ
์ด ํ์ด์ง์์๋ Kubernetes์ฉ Apigee APIM Operator๋ฅผ ์ฌ์ฉํ์ฌ Google Kubernetes Engine(GKE) ๊ฒ์ดํธ์จ์ด์ Apigee ๋ฐํ์ ์ ์ฑ ๋ฐ Google ํ ํฐ ์ฝ์ ์ ์ฑ ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค. ๊ฒ์ดํธ์จ์ด์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ ์ฑ ์งํฉ์ ์ถ๊ฐํ๋ฉด API ์ ํ ์ํ์ ๋์ด ๋ณด์ ๋ฐ ๋น์ฆ๋์ค ๊ท์น์ ์ถ๊ฐํ์ฌ ๊ฒ์ดํธ์จ์ด์ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์์ต๋๋ค.
Kubernetes์ฉ Apigee APIM Operator๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด์ ๋ค์ ์ ์ฑ ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
- SpikeArrest ์ ์ฑ
- JavaScript ์ ์ฑ
- Google ํ ํฐ ์ฝ์ ์ ์ฑ
- GenerateJWT ์ ์ฑ
- KVM ์ ์ฑ
- OASValidation ์ ์ฑ
- ServiceCallout ์ ์ฑ
- OAuthv2 ์ ์ฑ
- ResponseCache ์ ์ฑ
- VerifyAPIKey ์ ์ฑ
๊ฐ์
๋ค์ ์น์ ์์๋ ์๋ ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.
- GKE ๊ฒ์ดํธ์จ์ด์ ์ ์ฑ ์ ์ถ๊ฐํฉ๋๋ค.
- ์ ์ฑ ์ฌ์ฉ์ ์ํํ๋ ํ ํ๋ฆฟ ๊ท์น์ ๋ง๋ญ๋๋ค.
- ํ ํ๋ฆฟ ๊ท์น์ ์ฌ์ฉํ๋ Apigee ํ ํ๋ฆฟ์ ๋ง๋ญ๋๋ค.
- ํ ํ๋ฆฟ์ ์ฌ์ฉํ์ฌ Apigee Gateway ์ ์ฑ ์ ๋ฐฐํฌํฉ๋๋ค.
- ์ ์ฑ ์ํ์ ํ์ธํฉ๋๋ค.
์์ํ๊ธฐ ์ ์
์ด ๊ฐ์ด๋์ ์์๋ก ์ฌ์ฉ๋ ์ ์ฒด ์ ์ฑ ์งํฉ์ผ๋ก GKE ๊ฒ์ดํธ์จ์ด๋ฅผ ์์ ํ๋ ค๋ฉด Apigee ๋ด์์ ํ ํฐ์ ๋ง๋ค๊ณ ํ๋ก์ ๋ฐ ํ์ฅ ํ๋ก๊ทธ๋จ์ ๋ฐฐํฌํ๋ ๋ฐ ํ์ํ ์ญํ ์ด ์๋ ์๋น์ค ๊ณ์ ์ด ์์ด์ผ ํฉ๋๋ค. Google ํ ํฐ์ ๋ง๋ค์ง ์๋ ๊ฒฝ์ฐ ์๋น์ค ๊ณ์ ์ ์ถ๊ฐ ์ญํ ์ ์ถ๊ฐํ ํ์๊ฐ ์์ผ๋ฉฐ ๋ค์ ์น์ ์ผ๋ก ๊ฑด๋๋ธ ์ ์์ต๋๋ค.
ํ์ํ ๊ถํ์ด ์๋ ์๋น์ค ๊ณ์ ์ ๋ง๋ค๋ ค๋ฉด ๋ค์ ์๋ด๋ฅผ ๋ฐ๋ฅด์ธ์.
- Kubernetes์ฉ Apigee APIM Operator ์ค์น ๊ฐ์ด๋์์
apigee-apim-gsa
๋ผ๋ ์๋น์ค ๊ณ์ ์ ๋ง๋ ๊ฒฝ์ฐ ์ด ๋จ๊ณ๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ค์ ๋จ๊ณ๋ก ์งํํ ์ ์์ต๋๋ค. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์๋น์ค ๊ณ์ ์ ๋ง๋ญ๋๋ค.gcloud iam service-accounts create apigee-apim-gsa --project=$PROJECT_ID
- ์๋น์ค ๊ณ์ ์ ํ ํฐ์ ๋ง๋๋ ๋ฐ ํ์ํ ์ญํ ์ ๋ถ์ฌํฉ๋๋ค.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member "serviceAccount:apigee-apim-gsa@$PROJECT_ID.iam.gserviceaccount.com" \ --role "roles/iam.serviceAccountTokenCreator"
apigee-apim-gsa
์๋น์ค ๊ณ์ ์ ํ๋ก์ ๋ฐ ํ์ฅ ํ๋ก๊ทธ๋จ์ ๋ฐฐํฌํ๋ ๋ฐ ํ์ํ ์ญํ ์ ๋ถ์ฌํฉ๋๋ค.gcloud projects add-iam-policy-binding $PROJECT_ID \ --member "serviceAccount:apigee-apim-gsa@$PROJECT_ID.iam.gserviceaccount.com" \ --role "roles/iam.serviceAccountUser"
์ ์ฑ ์ผ๋ก GKE ๊ฒ์ดํธ์จ์ด ์์
ํ๋ ์ด์์ ์ ์ฑ
์ผ๋ก GKE ๊ฒ์ดํธ์จ์ด๋ฅผ ์์ ํ์ฌ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์์ต๋๋ค. ์ด ์์ ๋๋ฌ๋ณด๊ธฐ์์๋ ๋ ๊ฐ์ Apigee ์ ์ฑ
๋ฐ Google ํ ํฐ ์ฝ์
์ ์ฑ
์ ๊ดํ ์ฌ์์ด ํฌํจ๋ yaml
ํ์ผ์ ๊ฒ์ดํธ์จ์ด์ ์ ์ฉํฉ๋๋ค.
๋ค์ yaml
ํ์ผ์ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด์ ์ ์ฉ๋ ๊ฐ ์ ์ฑ
์ ๊ฒ์ดํธ์จ์ด๋ก ์ ์ก๋ ์์ฒญ์ ํ๊ฐํ ๋ ์๋ก ๋ค๋ฅธ ์ญํ ์ ์ํํฉ๋๋ค.
- SpikeArrest ์ ์ฑ ์ ์๊ฐ ๋จ์๋น ํ์ฉ๋๋ ์ต๋ ์์ฒญ ๋น์จ์ ์ ์ํ์ฌ ์ต๋ ๋ฉ์์ง ๋น์จ์ ์ ์ดํฉ๋๋ค. ์ด ์์์์ ์ต๋ ๋น์จ์ ๋ถ๋น 5๋ก ์ค์ ๋ฉ๋๋ค. SpikeArrest ์ ์ฑ ์ ์ฌ์ฉํ์ฌ ํธ๋ํฝ์ ๊ธ์ฆ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๊ดํ ์์ธํ ๋ด์ฉ์ SpikeArrest ์ ์ฑ ์ ์ฐธ์กฐํ์ธ์.
- JavaScript ์ ์ฑ ์ ์ฌ์ฉํ๋ฉด ๊ฒ์ดํธ์จ์ด ์์ฒญ์ ์ปค์คํ JavaScript ์ฝ๋๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ด ์์์์๋ ์ ์ฑ ์ด ์์ฒญ์ ์ปค์คํ ํค๋๋ฅผ ์ถ๊ฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. JavaScript ์ ์ฑ ์ ์ฌ์ฉํ์ฌ ์ปค์คํ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ๊ดํ ์์ธํ ๋ด์ฉ์ JavaScript ์ ์ฑ ์ ์ฐธ์กฐํ์ธ์.
- Google ํ ํฐ ์ฝ์ ์ ์ฑ ์ AssignMessage ์ ์ฑ ์ ์ฌ์ฉํ์ฌ Google ์ธ์ฆ ์ก์ธ์ค ํ ํฐ์ ๊ฒ์ดํธ์จ์ด ์์ฒญ์ ์ฝ์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. Apigee์์๋ Google OAuth ํ ํฐ ๋๋ OpenID Connect ํ ํฐ์ ์ฌ์ฉํ์ฌ Google ์๋น์ค๋ก ์ธ์ฆํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ์ธ์ฆ ํ ํฐ์ ๊ดํ ์์ธํ ๋ด์ฉ์ Google ์ธ์ฆ ์ฌ์ฉ์ ์ฐธ์กฐํ์ธ์.
๊ฒ์ดํธ์จ์ด์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฑ ์ ์ถ๊ฐํฉ๋๋ค.
apim
๋ค์์คํ์ด์ค์apigee-policies.yaml
์ด๋ผ๋ ์ ํ์ผ์ ๋ง๋ญ๋๋ค.- ๋ค์ ํ์ผ์ ์ฝํ
์ธ ๋ฅผ ์๋ก ๋ง๋ ํ์ผ์ ๋ณต์ฌํฉ๋๋ค.
# apigee-policies.yaml apiVersion: apim.googleapis.com/v1 kind: SpikeArrest metadata: name: spike-arrest namespace: apim spec: identifier: ref: request.header.name useEffectiveCount: true peakMessageRate: value: "5pm" --- apiVersion: apim.googleapis.com/v1 kind: Javascript metadata: name: js-add-headers namespace: apim spec: timeLimit: 2000 source: | var sum = 1+1; context.setVariable("request.header.first", 1); context.setVariable("request.header.second", 1); context.setVariable("request.header.sum", sum); --- apiVersion: apim.googleapis.com/v1 kind: AssignMessage metadata: name: google-token-policy namespace: apim spec: setActions: - authentication: googleAccessToken: scopes: - 'https://www.googleapis.com/auth/cloud-platform' AssignTo: createNew: false type: request --- apiVersion: apim.googleapis.com/v1 kind: KVM metadata: name: kvm-1 namespace: apim spec: delete: - keys: - value: mykey description: kvm1 displayName: kvm1 exclusiveCache: true expiryTimeInSecs: 3600 get: - assignTo: response.header.mykvm index: 0 keys: - value: mykey initialEntries: - keys:s - key1 values:s - val1 - keys:s - mykey values: - initvalue isEncrypted: false mapIdentifier: mapIdentifier mapName:s ref: kvm.mapname value: kvmname put: - keys: - value: mykey values: - value: request.header.mykvm scope: environment --- apiVersion: apim.googleapis.com/v1 kind: OASValidation metadata: name: oas-validation-1 spec: openApiSpec: | openapi: 3.0.4 info: title: Sample API description: Optional multi/single line description. version: 0.1.9 servers: - url: http://apigee-apim-operator-test.apigee.net description: Optional server description, our main host in httproute paths: /get: get: summary: just for test description: Optional extended description in CommonMark or HTML. parameters: - name: X-Request-Type in: header description: Must be 'internal' or 'external'. required: true schema: type: string enum: - internal - external responses: '200': # status code description: A JSON object content: application/json: schema: type: object properties: headers: type: object source: request --- apiVersion: apim.googleapis.com/v1 kind: ServiceCallout metadata: name: service-callout-1 namespace: apim spec: request: clearPayload: true variable: myRequest ignoreUnresolvedVariables: true removeActions: - payload: true - queryParams: - name: rq-param1 - name: rq-param2 copyActions: - version: true - verb: true addActions: - headers: - name: X-header1 value: value1 - name: X-header2 value: value2 - queryParams: - name: q-param1 value: value1 - name: q-param2 value: value2 setActions: - verb: PUT - formParams: - name: f-param1 value: value1 - name: f-param2 value: value2 response: calloutResponse timeout: 30000 httpTargetConnection: URL: https://httpbin.org/put properties: - name: success.codes value: 1xx,2xx,3xx,400 - name: supports.http11 value: "true"
- ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด์
yaml
ํ์ผ์ ์ ์ฉํฉ๋๋ค.kubectl -n apim apply -f apigee-policies.yaml
TemplateRule์ SharedFlow ํ ํ๋ฆฟ์ผ๋ก ๋ง๋ค๊ธฐ
์ด ๋จ๊ณ์์๋ ๊ฒ์ดํธ์จ์ด์ ์ถ๊ฐํ ์ ์ฑ
์ ์ ์ฉํ TemplateRule
์ ๋ง๋ญ๋๋ค.
ํ
ํ๋ฆฟ ๊ท์น์ ์๋น์ค ๊ฐ๋ฐ์๊ฐ ๊ฒ์ดํธ์จ์ด ํธ๋ํฝ์ ์น์ธ๋ ์ ์ฑ
๋ง ์ ์ฉํ๋๋ก ์กฐ์ง ๊ด๋ฆฌ์๊ฐ ๋ง๋ SharedFlows์ ๊ท์น์
๋๋ค. ํ
ํ๋ฆฟ ๊ท์น์ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ์๊ฐ ์ฌ์ฉํ ์ ์๋ ์ ์ฑ
, ํน์ ์ฌ์ฉ ์ฌ๋ก์ ํ์ํ ์ ์ฑ
, ์๋น์ค ๊ฐ๋ฐ์๊ฐ ์ฌ์ฉํ ์ ์๋ ์ ์ฑ
์ ํ์
ํ ์ ์์ต๋๋ค.
ํ ํ๋ฆฟ ๊ท์น ๋ง๋ค๊ธฐ
AssignMessage ์ ์ฑ ์ ์ฌ์ฉ์ ์ ์ฉํ๋ ํ ํ๋ฆฟ ๊ท์น์ ๋ง๋ญ๋๋ค.
apim
๋ค์์คํ์ด์ค์template-rule.yaml
์ด๋ผ๋ ์yaml
ํ์ผ์ ๋ง๋ญ๋๋ค.- ๋ค์ ํ์ผ์ ์ฝํ
์ธ ๋ฅผ ์๋ก ๋ง๋ ํ์ผ์ ๋ณต์ฌํฉ๋๋ค.
# template-rule.yaml apiVersion: apim.googleapis.com/v1 kind: ApimTemplateRule metadata: name: template-rule namespace: apim spec: allowList: [SpikeArrest, Javascript, GenerateJWT, KVM, OASValidation, OAuthv2, ServiceCallout] requiredList: [AssignMessage] denyList: []
์ด ์์์์ ํ ํ๋ฆฟ ๊ท์น์ ๊ฐ๋ฐ์์๊ฒ Google ํ ํฐ ์ฝ์ ์ ์ฑ ์ ์ค๋ช ํ๋ AssignMessage ์ ์ฑ ์ด ํ์ํ๋ค๊ณ ์๋ ค์ค๋๋ค. ๋ํ ๊ฐ๋ฐ์์๊ฒ API ๊ด๋ฆฌ์์ SpikeArrest, JavaScript, GenerateJWT, KVM, OASValidation, OAuthv2, ServiceCallout ์ ์ฑ ์ ์ฌ์ฉํ ์ ์๋ค๊ณ ์๋ดํฉ๋๋ค. ๊ฑฐ๋ถ ๋ชฉ๋ก์ ์ง์ ๋ ์ ์ฑ ์ด ์์ต๋๋ค.
ํ ํ๋ฆฟ ๊ท์น ์ ์ฉ
๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ํ ํ๋ฆฟ ๊ท์น์ ์ ์ฉํฉ๋๋ค.
kubectl apply -f template-rule.yaml
ํ ํ๋ฆฟ ๊ท์น์ ์ฌ์ฉํ Apigee ํ ํ๋ฆฟ ๋ง๋ค๊ธฐ
์ด์ ์น์ ์์ ๋ง๋ ํ ํ๋ฆฟ ๊ท์น์ ํฌํจํ๋ Apigee ํ ํ๋ฆฟ์ ๋ง๋ญ๋๋ค.
apim
๋ค์์คํ์ด์ค์new-admin-template.yaml
์ด๋ผ๋ ์yaml
ํ์ผ์ ๋ง๋ญ๋๋ค.- ๋ค์ ํ์ผ์ ์ฝํ
์ธ ๋ฅผ ์๋ก ๋ง๋ ํ์ผ์ ๋ณต์ฌํฉ๋๋ค.
# new-admin-template.yaml apiVersion: apim.googleapis.com/v1 kind: ApimTemplate metadata: name: new-admin-template namespace: apim spec: apimTemplateRule: group: apim.googleapis.com kind: ApimTemplateRule name: template-rule namespace: apim templates: - mode: REQUEST flows: - name: preflow policies: - group: apim.googleapis.com kind: OASValidation name: oas-validation-1 namespace: apim - group: apim.googleapis.com kind: SpikeArrest name: spike-arrest namespace: apim - name: ConditionalGetFlow policies: - group: apim.googleapis.com kind: Javascript name: js-add-headers namespace: apim condition: request.verb="GET" - name: postflow policies: - group: apim.googleapis.com kind: AssignMessage name: google-token-policy namespace: apim - group: apim.googleapis.com kind: ServiceCallout name: service-callout-1 namespace: apim - mode: RESPONSE flows: - name: postflow policies: - group: apim.googleapis.com kind: KVM name: kvm-1 namespace: apim
- ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ
ํ๋ฆฟ์ ์ ์ฉํฉ๋๋ค.
kubectl apply -f new-admin-template.yaml
Apigee ๊ฒ์ดํธ์จ์ด ์ ์ฑ ๋ฐฐํฌ
์ด ๋จ๊ณ์์๋ ApigeeGatewayPolicy
์ฌ์์ด ํฌํจ๋ ์ ํ์ผ์ ๊ฒ์ดํธ์จ์ด์ ์ ์ฉํฉ๋๋ค.
์ด ์ ์ฑ
์ Apigee ํ
ํ๋ฆฟ์ ๊ฒ์ดํธ์จ์ด์ ๋ฐฐํฌํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
Apigee ๊ฒ์ดํธ์จ์ด ์ ์ฑ ์ ๋ฐฐํฌํฉ๋๋ค.
apim
๋ค์์คํ์ด์ค์apigee-gateway-policy-withSA.yaml
์ด๋ผ๋ ์yaml
ํ์ผ์ ๋ง๋ญ๋๋ค.- ๋ค์ ํ์ผ์ ์ฝํ
์ธ ๋ฅผ ์๋ก ๋ง๋ ํ์ผ์ ๋ณต์ฌํฉ๋๋ค.
# apigee-gateway-policy-withSA.yaml apiVersion: apim.googleapis.com/v1 kind: ApigeeGatewayPolicy metadata: name: apim-template-injection namespace: apim spec: serviceAccount: apigee-apim-gsa@PROJECT_ID.iam.gserviceaccount.com ref: group: apim.googleapis.com kind: ApimTemplate name: new-admin-template namespace: apim targetRef: group: apim.googleapis.com kind: APIMExtensionPolicy name: global-ext-lb1-apim-policy namespace: apim
- ์ ์ฑ
์ ์ ์ฉํฉ๋๋ค.
kubectl apply -f apigee-gateway-policy-withSA.yaml
- ์ ๊ฒ์ดํธ์จ์ด ์ ์ฑ
์ ๋ฐฐํฌ ์ํ๋ฅผ ํ์ธํฉ๋๋ค.
kubectl -n apim get ApigeeGatewayPolicy
๋ฐฐํฌํ๋ฉด ์ ์ฑ
STATUS
์CREATED
๊ฐ ํ์๋ฉ๋๋ค.
์ ๊ฒ์ดํธ์จ์ด ์ ์ฑ ์ด ๋ฐฐํฌ๋๋ฉด 2๋ถ ์ ๋ ๊ธฐ๋ค๋ฆฐ ํ ๊ฒ์ดํธ์จ์ด์ ์์ฒญ์ ์ ์กํ์ฌ ์ ์ฑ ์ด ํด๋ฌ์คํฐ์ ์ ํ๋๋๋ก ํฉ๋๋ค.
์ ์ฑ ์ํ ํ์ธ
Apigee ๊ฒ์ดํธ์จ์ด ์ ์ฑ ์ด ์์๋๋ก ์๋ํ๋์ง ํ์ธํ๋ ค๋ฉด ๋ค์ ์น์ ์ ์ค๋ช ๋ ๋๋ก ๊ฒ์ดํธ์จ์ด์ ์์ฒญ์ ์ ์กํฉ๋๋ค.
AssignMessage ์ ์ฑ ์ํ
AssignMessage ์ ์ฑ ์ ์ฌ์ฉํ์ฌ {company_name} ํ ํฐ์ด ์์ฒญ์ ์ฝ์ ๋์๋์ง ํ์ธํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด์ ์์ฒญ์ ์ ์กํฉ๋๋ค.
curl http://GATEWAY_IP_ADDRESS/get -H "Host: HOST_NAME" -H "x-api-key: API_KEY"
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค.kubectl get gateway GATEWAY_NAME
HOST_NAME
์ ํธ์คํธ์ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ API ํค ๊ฐ์ ๋๋ค.
์ฑ๊ณต์ ์ธ ์๋ต์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑ๋ Bearer ํ ํฐ๊ณผ ํจ๊ป Authorization
ํค๋๊ฐ ํฌํจ๋์ด์ผ ํฉ๋๋ค.
{ "args": {}, "headers": { "Accept": "*/*", "Authorization": "Bearer ya29.c.c0ASRK0Gbw03y9cfvxL11DxaRYBQUU18SmUP4Vu63OckHI5cX7wJ4DmGMG2vbDDS69HXJHqMj-lak4tcqOsJGmE65crn2gNuJLanXidwM8", "First": "1.0", "Host": "apigee-apim-operator-test.apigee.net", "Second": "1.0", "Sum": "2", "User-Agent": "curl/8.7.1", "X-Api-Key": "McYcHGR3PTSGLXExvKADwQ1JJeCjgPDUvAakCl0rJKCFaX0Y", "X-Cloud-Trace-Context": "0fd3dadc2a3c328fa968d5f5f1434c29/18300783092696918345" }, "origin": "34.54.108.129", "url": "apigee-apim-operator-test.apigee.net/get" }
SpikeArrest ์ ์ฑ ์ํ
1๋ถ ์ด๋ด์ ๊ฒ์ดํธ์จ์ด์ ์์ฒญ์ 10๋ฒ ์ ์กํ์ฌ SpikeArrest ์ ์ฑ ์ ์ ์ฉ์ ํ ์คํธํ ์ ์์ต๋๋ค.
๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ฌ ์์ฒญ์ ์์ฑํ ์ ์์ต๋๋ค.
#!/bin/sh for i in $(seq 1 11); do curl http://GATEWAY_IP_ADDRESS/get -H "Host: HOST_NAME" -H "x-api-key: API_KEY" sleep 1 done
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์GATEWAY_NAME
์ ๊ฒ์ดํธ์จ์ด ์ด๋ฆ์ ๋๋ค.kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
์ ๊ฒ์ดํธ์จ์ด์HTTPRoute
์ ์ ์๋ ํธ์คํธ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ ํ ์คํธ ์ค์ ์์ ํ๋ํ API ํค ๊ฐ์ ๋๋ค.
๋ค์๊ณผ ๋น์ทํ ์๋ต์ด ํ์๋ฉ๋๋ค.
"fault":{"faultstring":"Spike arrest violation. Allowed rate : MessageRate{capacity=5, period=Minutes}","detail":{"errorcode":"policies.ratelimit.SpikeArrestViolation"}}}
JavaScript ์ ์ฑ ์ํ
JavaScript ์ ์ฑ ์ด ์์๋๋ก ์๋ํ๋์ง ํ์ธํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด์ ์์ฒญ์ ์ ์กํฉ๋๋ค.
curl http://GATEWAY_IP_ADDRESS/get \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -i
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์GATEWAY_NAME
์ ๊ฒ์ดํธ์จ์ด ์ด๋ฆ์ ๋๋ค.kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
์ ๊ฒ์ดํธ์จ์ด์HTTPRoute
์ ์ ์๋ ํธ์คํธ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ ํ ์คํธ ์ค์ ์์ ํ๋ํ API ํค ๊ฐ์ ๋๋ค.
JavaScript ์ ์ฑ
์ ์๋ต์ ํ์๋ ๋๋ก First
, Second
, Sum
์ 3๊ฐ์ง ์์ฒญ ํค๋๋ฅผ ์ค์ ํฉ๋๋ค.
HTTP/1.1 200 OK ... { "args": {}, "headers": { ... "First": "1.0", ... "Second": "1.0", "Sum": "2", ... }, ... }
OASValidation ์ ์ฑ ์ํ
OASValidation ์ ์ฑ ์ด ์์๋๋ก ์๋ํ๋์ง ํ์ธํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด์ ์์ฒญ์ ์ ์กํฉ๋๋ค.
curl "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: badvalue"
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์GATEWAY_NAME
์ ๊ฒ์ดํธ์จ์ด ์ด๋ฆ์ ๋๋ค.kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
์ ๊ฒ์ดํธ์จ์ด์HTTPRoute
์ ์ ์๋ ํธ์คํธ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ ํ ์คํธ ์ค์ ์์ ํ๋ํ API ํค ๊ฐ์ ๋๋ค.
๋ช
๋ น์ด์ ์๋ชป๋ X-Request-Type
ํค๋ ๊ฐ์ด ํฌํจ๋์ด ์์ต๋๋ค. ๋ค์๊ณผ ์ ์ฌํ ์๋ต์ด ํ์๋๋ฉด์ ์์ฒญ์ด ์คํจํฉ๋๋ค.
{"fault":{"faultstring":"OASValidation oas-validation-1 with resource \"oas:\/\/oas-validation-1.yaml\": failed with reason: \"[ERROR - Instance value (\"badvalue\") not found in enum (possible values: [\"internal\",\"external\"]): []]\"","detail":{"errorcode":"steps.oasvalidation.Failed"}}}
์ ํจํ X-Request-Type
ํค๋ ๊ฐ์ ์ฌ์ฉํ์ฌ ๋์ผํ ์์ฒญ์ ์ ์กํ๋ฉด ์ฑ๊ณตํฉ๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
curl "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -i
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์GATEWAY_NAME
์ ๊ฒ์ดํธ์จ์ด ์ด๋ฆ์ ๋๋ค.kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
HOST_NAME
์ ๊ฒ์ดํธ์จ์ด์HTTPRoute
์ ์ ์๋ ํธ์คํธ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ ํ ์คํธ ์ค์ ์์ ํ๋ํ API ํค ๊ฐ์ ๋๋ค.
ServiceCallout ์ ์ฑ ์ํ
๋๋ฒ๊ทธ ์ธ์ ์ ์ด๊ณ ํ๋ก์์ ์ ํจํ ์์ฒญ์ ๋ช ๊ฐ ์ ์กํ์ฌ ServiceCallout ์ ์ฑ ์ ์ํ์ ํ์ธํ ์ ์์ต๋๋ค.
๋๋ฒ๊ทธ ์ธ์ ์ ์ด๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์.
- Google Cloud ์ฝ์์์ API ํ๋ก์ ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค.
- Kubernetes์ฉ Apigee APIM Operator๋ฅผ ์ํด ์์ฑ๋ ํ๊ฒฝ์ ๋ฐฐํฌํ
global-ext-lb1-apim-policy
ํ๋ก์๋ฅผ ์ ํํฉ๋๋ค. - ๋๋ฒ๊ทธ ํญ์ ํด๋ฆญํฉ๋๋ค.
- ๋๋ฒ๊ทธ ์ธ์ ์ฐฝ์์ ๋๋ฒ๊ทธ ์ธ์ ์์์ ํด๋ฆญํฉ๋๋ค.
- Debug session ์ฐฝ์์ ๋ค์๊ณผ ๊ฐ์ด ์ ํํฉ๋๋ค.
- ํ๊ฒฝ: ์ฌ์ฉ ๊ฐ๋ฅํ ํ๊ฒฝ ๋ชฉ๋ก์์ APIM Operator์ฉ์ผ๋ก ๋ง๋ ํ๊ฒฝ์ ์ ํํฉ๋๋ค.
- ํํฐ: ์์(๋ชจ๋ ํธ๋์ญ์ )์ ์ ํํฉ๋๋ค.
- ์์์ ํด๋ฆญํฉ๋๋ค.
์ธ์ ์ด ์์๋๋ฉด ์ ํจํ ์์ฒญ์ ํ๋ก์์ ๋ณด๋ผ ์ ์์ต๋๋ค.
curl "GATEWAY_IP_ADDRESSget" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -i
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์GATEWAY_NAME
์ ๊ฒ์ดํธ์จ์ด ์ด๋ฆ์ ๋๋ค.kubectl get gateway GATEWAY_NAME
HOST_NAME
์ ๊ฒ์ดํธ์จ์ด์HTTPRoute
์ ์ ์๋ ํธ์คํธ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ ํ ์คํธ ์ค์ ์์ ํ๋ํ API ํค ๊ฐ์ ๋๋ค.
์์ฒญ ๋ฐ ์๋ต ํธ๋์ญ์
์ด ํธ๋์ญ์
์ฐฝ์ ํ์๋ฉ๋๋ค. ๋ชฉ๋ก์์ ์ฑ๊ณตํ ํธ๋์ญ์
์ ์ ํํ์ฌ ํ๋ฆ์ ํ์ํฉ๋๋ค. ServiceCallout
์ ์ฑ
์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋์์์ ํ์ธํ ์ ์์ต๋๋ค.
KVM ์ ์ฑ ์ํ
KVM ์ ์ฑ
์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋๋ฉด mykey
ํค์ ์์ ๊ฐ์ผ๋ก KVM์ ์ด๊ธฐํํฉ๋๋ค.
์๋ต ํธ๋์ญ์
์ด ์์ผ๋ฉด KVM ์ ์ฑ
์ด mykey
๊ฐ์ ๊ฒ์ํ์ฌ ์๋ต ํค๋ mykvm
์ ์ ์ฅํฉ๋๋ค.
KVM ์ ์ฑ
์ด ๋ค์ ์คํ๋๋ฉด ์์ฒญ ํค๋ mykvm
์์ ๊ฐ์ ธ์จ mykey
์ ์ ๊ฐ์ด ์ฝ์
๋ฉ๋๋ค.
๊ฐ ํธ๋์ญ์ ์ ํค๋๋ฅผ ํ์ธํ์ฌ ์ ์ฑ ์ด ํ ํธ๋์ญ์ ์์ KVM์ ๊ฐ์ ์ ์ฅํ๊ณ ๋ค์ ํธ๋์ญ์ ์์ ๋์ผํ ๊ฐ์ ๊ฒ์ํ๋์ง ํ์ธํ ์ ์์ต๋๋ค(๋ค์ ์ ์ฐธ๊ณ ).
KVM ์ ์ฑ ์ ํ ์คํธํฉ๋๋ค.
- ์์ฒญ์ ๊ฒ์ดํธ์จ์ด์ ๋ณด๋
๋๋ค.
curl -i "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" \ -H "KVM_NAME: next-value1" -i
๊ฐ ํญ๋ชฉ์ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
GATEWAY_IP_ADDRESS
๋ ๊ฒ์ดํธ์จ์ด์ IP ์ฃผ์์ ๋๋ค. ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด IP ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์GATEWAY_NAME
์ ๊ฒ์ดํธ์จ์ด ์ด๋ฆ์ ๋๋ค.kubectl get gateway GATEWAY_NAME
HOST_NAME
์ ๊ฒ์ดํธ์จ์ด์HTTPRoute
์ ์ ์๋ ํธ์คํธ ์ด๋ฆ์ ๋๋ค.API_KEY
๋ ํ ์คํธ ์ค์ ์์ ํ๋ํ API ํค ๊ฐ์ ๋๋ค.KVM_NAME
์ KVM์ ์ด๋ฆ์ ๋๋ค.
- ์๋ต ํค๋๋ฅผ ํ์ธํ์ฌ KVM ์ ์ฑ
์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋์๊ณ ์ด๊ธฐ ๊ฐ์ด
mykvm
์ ์ ์ฅ๋์๋์ง ํ์ธํฉ๋๋ค. ๋ค์๊ณผ ๋น์ทํ ์๋ต์ด ํ์๋ฉ๋๋ค.HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * Content-Length: 517 content-type: application/json date: ... server: gunicorn/19.9.0 mykvm: initvalue via: 1.1 google { "args": { ... "url": "http://apigee-apim-operator-test.apigee.net/get" } }
- ๊ฒ์ดํธ์จ์ด์ ๋ค๋ฅธ ์์ฒญ์ ๋ณด๋
๋๋ค.
curl -i "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "mykvm: next"X-Request-Type: external" -H "mykvm: next-value2" -i
์๋ต์ ๋ค์๊ณผ ๋น์ทํ๊ฒ ํ์๋ฉ๋๋ค.
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * Content-Length: 517 content-type: application/json date: ... server: gunicorn/19.9.0 mykvm: next-value2 via: 1.1 google { "args": { ... "url": "http://apigee-apim-operator-test.apigee.net/get?rq-param2=rq-val1&x-param1=xval1" } }
mykvm
ํค๋ ๊ฐ์ด ์์ฒญ ํค๋mykvm
๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ๋์์ผ๋ฏ๋ก KVM ์ ์ฑ ์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋์์์ ํ์ธํ ์ ์์ต๋๋ค. - ์์ฒญ์ ํ ๋ฒ ๋ ๋ณด๋
๋๋ค.
curl -i "http://GATEWAY_IP_ADDRESS/get" \ -H "Host: HOST_NAME" \ -H "x-api-key: API_KEY" \ -H "X-Request-Type: external" -H "mykvm: next-value3" -i
์๋ต์ ๋ค์๊ณผ ๋น์ทํ๊ฒ ํ์๋ฉ๋๋ค.
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * Content-Length: 517 content-type: application/json date: ... server: gunicorn/19.9.0 mykvm: next-value2 via: 1.1 google { "args": { ... "url": "http://apigee-apim-operator-test.apigee.net/get?rq-param2=rq-val1&x-param1=xval1" } }
mykvm
ํค๋์ ๊ฐ์ด ๋ค์ ์ ๋ฐ์ดํธ๋์ด ์๋ต์ ํ์๋ ๊ฐ์ด ์ด์ ํธ๋์ญ์ ์ ์ ์ฅ๋ ๊ฐ์์ ๋ณด์ฌ์ค๋๋ค.
๋ฌธ์ ํด๊ฒฐ
GKE ๊ฒ์ดํธ์จ์ด์ ์ ์ฑ ์ ์ถ๊ฐํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด APIM Operator ๋ฌธ์ ํด๊ฒฐ์์ ์ผ๋ฐ์ ์ธ ์ค๋ฅ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐธ์กฐํ์ธ์.
๋ค์ ๋จ๊ณ
- SpikeArrest ์ ์ฑ ์ ๋ํด ์์ธํ ์์๋ณด์ธ์.
- JavaScript ์ ์ฑ ์ ๋ํด ์์ธํ ์์๋ณด์ธ์.